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
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
@@ -65,7 +66,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
||||
|
||||
var n v3.Callback
|
||||
_ = 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)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
@@ -46,7 +47,7 @@ func TestComponents_MarshalYAML(t *testing.T) {
|
||||
|
||||
var n v3.Components
|
||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||
_ = n.Build(idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||
|
||||
r := NewComponents(&n)
|
||||
|
||||
|
||||
@@ -5,16 +5,22 @@ package v3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
||||
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"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
|
||||
@@ -22,7 +28,7 @@ var lowDoc *lowv3.Document
|
||||
func initTest() {
|
||||
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||
AllowFileReferences: true,
|
||||
AllowRemoteReferences: true,
|
||||
@@ -382,9 +388,9 @@ func testBurgerShop(t *testing.T, h *Document, checkLines bool) {
|
||||
func TestStripeAsDoc(t *testing.T) {
|
||||
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||
assert.Len(t, err, 3)
|
||||
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||
d := NewDocument(lowDoc)
|
||||
assert.NotNil(t, d)
|
||||
}
|
||||
@@ -402,7 +408,7 @@ func TestK8sAsDoc(t *testing.T) {
|
||||
func TestAsanaAsDoc(t *testing.T) {
|
||||
data, _ := os.ReadFile("../../../test_specs/asana.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
@@ -412,10 +418,51 @@ func TestAsanaAsDoc(t *testing.T) {
|
||||
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) {
|
||||
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
|
||||
baseURL, _ := url.Parse("https://raw.githubusercontent.com/digitalocean/openapi/82e1d558e15a59edc1d47d2c5544e7138f5b3cbf/specification")
|
||||
config := datamodel.DocumentConfiguration{
|
||||
@@ -424,12 +471,53 @@ func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
||||
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)
|
||||
if err != nil {
|
||||
for e := range err {
|
||||
fmt.Println(err[e])
|
||||
er := utils.UnwrapErrors(err)
|
||||
for e := range er {
|
||||
fmt.Printf("Reported Error: %s\n", er[e])
|
||||
}
|
||||
panic("broken something")
|
||||
}
|
||||
d := NewDocument(lowDoc)
|
||||
assert.NotNil(t, d)
|
||||
@@ -439,7 +527,7 @@ func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
||||
func TestPetstoreAsDoc(t *testing.T) {
|
||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
@@ -452,10 +540,10 @@ func TestPetstoreAsDoc(t *testing.T) {
|
||||
func TestCircularReferencesDoc(t *testing.T) {
|
||||
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||
assert.Len(t, err, 3)
|
||||
d := NewDocument(lowDoc)
|
||||
|
||||
lDoc, err := lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
||||
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||
d := NewDocument(lDoc)
|
||||
assert.Len(t, d.Components.Schemas, 9)
|
||||
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
||||
}
|
||||
@@ -604,7 +692,7 @@ components:
|
||||
numPatties: 1`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||
AllowFileReferences: true,
|
||||
AllowRemoteReferences: true,
|
||||
@@ -657,7 +745,7 @@ components:
|
||||
required: true`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||
AllowFileReferences: true,
|
||||
AllowRemoteReferences: true,
|
||||
@@ -685,7 +773,7 @@ components:
|
||||
`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||
AllowFileReferences: true,
|
||||
AllowRemoteReferences: true,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -20,7 +21,7 @@ func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
||||
// load the petstore spec
|
||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
@@ -110,7 +111,7 @@ func TestMediaType_MarshalYAML(t *testing.T) {
|
||||
// load the petstore spec
|
||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
var err []error
|
||||
var err error
|
||||
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||
if err != nil {
|
||||
panic("broken something")
|
||||
@@ -161,7 +162,7 @@ func TestMediaType_Examples(t *testing.T) {
|
||||
|
||||
var n v3.MediaType
|
||||
_ = 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)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
@@ -43,7 +44,7 @@ clientCredentials:
|
||||
|
||||
var n v3.OAuthFlows
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewOAuthFlows(&n)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -43,7 +44,7 @@ callbacks:
|
||||
|
||||
var n v3.Operation
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewOperation(&n)
|
||||
|
||||
@@ -140,7 +141,7 @@ security: []`
|
||||
|
||||
var n v3.Operation
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewOperation(&n)
|
||||
|
||||
@@ -158,7 +159,7 @@ func TestOperation_NoSecurity(t *testing.T) {
|
||||
|
||||
var n v3.Operation
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewOperation(&n)
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ package v3
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/utils"
|
||||
"os"
|
||||
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
@@ -19,17 +20,14 @@ func Example_createHighLevelOpenAPIDocument() {
|
||||
// Create a new *datamodel.SpecInfo from bytes.
|
||||
info, _ := datamodel.ExtractSpecInfo(data)
|
||||
|
||||
var err []error
|
||||
var err error
|
||||
|
||||
// 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.
|
||||
if len(err) > 0 {
|
||||
for i := range err {
|
||||
fmt.Printf("error: %e", err[i])
|
||||
}
|
||||
panic("something went wrong")
|
||||
for i := range utils.UnwrapErrors(err) {
|
||||
fmt.Printf("error: %v", i)
|
||||
}
|
||||
|
||||
// Create a high-level Document from the low-level one.
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -28,7 +29,7 @@ func TestPathItem(t *testing.T) {
|
||||
|
||||
var n v3.PathItem
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewPathItem(&n)
|
||||
|
||||
@@ -62,7 +63,7 @@ trace:
|
||||
|
||||
var n v3.PathItem
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewPathItem(&n)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -37,7 +38,7 @@ func TestPaths_MarshalYAML(t *testing.T) {
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
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)
|
||||
|
||||
high := NewPaths(&n)
|
||||
@@ -89,7 +90,7 @@ func TestPaths_MarshalYAMLInline(t *testing.T) {
|
||||
err := low.BuildModel(&idxNode, &n)
|
||||
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)
|
||||
|
||||
high := NewPaths(&n)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -38,7 +39,7 @@ links:
|
||||
|
||||
var n v3.Response
|
||||
_ = 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)
|
||||
|
||||
@@ -69,7 +70,7 @@ links:
|
||||
|
||||
var n v3.Response
|
||||
_ = 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)
|
||||
|
||||
@@ -97,7 +98,7 @@ links:
|
||||
|
||||
var n v3.Response
|
||||
_ = 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)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
@@ -30,7 +31,7 @@ func TestNewResponses(t *testing.T) {
|
||||
|
||||
var n v3.Responses
|
||||
_ = low.BuildModel(&idxNode, &n)
|
||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
||||
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||
|
||||
r := NewResponses(&n)
|
||||
|
||||
@@ -60,7 +61,7 @@ func TestResponses_MarshalYAML(t *testing.T) {
|
||||
|
||||
var n v3.Responses
|
||||
_ = 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)
|
||||
|
||||
@@ -90,7 +91,7 @@ func TestResponses_MarshalYAMLInline(t *testing.T) {
|
||||
|
||||
var n v3.Responses
|
||||
_ = 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)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
@@ -31,7 +32,7 @@ func TestSecurityScheme_MarshalYAML(t *testing.T) {
|
||||
|
||||
var n v3.SecurityScheme
|
||||
_ = 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)
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
@@ -23,7 +24,7 @@ type Contact struct {
|
||||
}
|
||||
|
||||
// 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)
|
||||
// not implemented.
|
||||
return nil
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
@@ -60,7 +61,7 @@ func (ex *Example) Hash() [32]byte {
|
||||
}
|
||||
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
ex.Reference = new(low.Reference)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
ex.Reference = new(low.Reference)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
i.Reference = new(low.Reference)
|
||||
i.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
// extract contact
|
||||
contact, _ := low.ExtractObject[*Contact](ContactLabel, root, idx)
|
||||
contact, _ := low.ExtractObject[*Contact](ctx, ContactLabel, root, idx)
|
||||
i.Contact = contact
|
||||
|
||||
// extract license
|
||||
lic, _ := low.ExtractObject[*License](LicenseLabel, root, idx)
|
||||
lic, _ := low.ExtractObject[*License](ctx, LicenseLabel, root, idx)
|
||||
i.License = lic
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
l.Reference = new(low.Reference)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
@@ -490,13 +491,13 @@ func (s *Schema) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
||||
// - UnevaluatedItems
|
||||
// - UnevaluatedProperties
|
||||
// - 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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
s.Reference = new(low.Reference)
|
||||
s.Index = idx
|
||||
if h, _, _ := utils.IsNodeRefValue(root); h {
|
||||
ref, err := low.LocateRefNode(root, idx)
|
||||
ref, _, err := low.LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
root = ref
|
||||
if err != nil {
|
||||
@@ -704,7 +705,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if extDocNode != nil {
|
||||
var exDoc ExternalDoc
|
||||
_ = 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}
|
||||
}
|
||||
|
||||
@@ -1069,7 +1070,7 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
||||
isRef := false
|
||||
refString := ""
|
||||
if h, _, l := utils.IsNodeRefValue(prop); h {
|
||||
ref, _ := low.LocateRefNode(prop, idx)
|
||||
ref, _, _ := low.LocateRefNode(prop, idx)
|
||||
if ref != nil {
|
||||
isRef = true
|
||||
prop = ref
|
||||
@@ -1165,7 +1166,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
||||
h := false
|
||||
if h, _, refLocation = utils.IsNodeRefValue(valueNode); h {
|
||||
isRef = true
|
||||
ref, _ := low.LocateRefNode(valueNode, idx)
|
||||
ref, _, _ := low.LocateRefNode(valueNode, idx)
|
||||
if ref != nil {
|
||||
valueNode = ref
|
||||
} else {
|
||||
@@ -1196,7 +1197,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
||||
h := false
|
||||
if h, _, refLocation = utils.IsNodeRefValue(vn); h {
|
||||
isRef = true
|
||||
ref, _ := low.LocateRefNode(vn, idx)
|
||||
ref, _, _ := low.LocateRefNode(vn, idx)
|
||||
if ref != nil {
|
||||
vn = ref
|
||||
} 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
|
||||
// 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.
|
||||
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
|
||||
errStr := "schema build failed: reference '%s' cannot be found at line %d, col %d"
|
||||
|
||||
isRef := false
|
||||
refLocation := ""
|
||||
|
||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||
// locate reference in index.
|
||||
isRef = true
|
||||
ref, _ := low.LocateRefNode(root, idx)
|
||||
ref, _, _ := low.LocateRefNode(root, idx)
|
||||
if ref != nil {
|
||||
schNode = ref
|
||||
schLabel = rl
|
||||
@@ -1260,9 +1262,13 @@ func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*S
|
||||
h := false
|
||||
if h, _, refLocation = utils.IsNodeRefValue(schNode); h {
|
||||
isRef = true
|
||||
ref, _ := low.LocateRefNode(schNode, idx)
|
||||
ref, foundIdx, _, nCtx := low.LocateRefNodeWithContext(ctx, schNode, idx)
|
||||
if ref != nil {
|
||||
schNode = ref
|
||||
if foundIdx != nil {
|
||||
//idx = foundIdx
|
||||
}
|
||||
ctx = nCtx
|
||||
} else {
|
||||
return nil, fmt.Errorf(errStr,
|
||||
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 {
|
||||
// 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]{
|
||||
Value: schema, KeyNode: schLabel, ValueNode: schNode, ReferenceNode: isRef,
|
||||
Reference: refLocation,
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
@@ -51,14 +52,16 @@ type SchemaProxy struct {
|
||||
buildError error
|
||||
isReference bool // Is the schema underneath originally a $ref?
|
||||
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.
|
||||
// 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.vn = value
|
||||
sp.idx = idx
|
||||
sp.ctx = ctx
|
||||
if rf, _, r := utils.IsNodeRefValue(value); rf {
|
||||
sp.isReference = true
|
||||
sp.referenceLookup = r
|
||||
@@ -83,7 +86,7 @@ func (sp *SchemaProxy) Schema() *Schema {
|
||||
}
|
||||
schema := new(Schema)
|
||||
utils.CheckForMergeNodes(sp.vn)
|
||||
err := schema.Build(sp.vn, sp.idx)
|
||||
err := schema.Build(sp.ctx, sp.vn, sp.idx)
|
||||
if err != nil {
|
||||
sp.buildError = err
|
||||
return nil
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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)
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
s.Reference = new(low.Reference)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package base
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
t.Reference = new(low.Reference)
|
||||
t.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
// extract externalDocs
|
||||
extDocs, err := low.ExtractObject[*ExternalDoc](ExternalDocsLabel, root, idx)
|
||||
extDocs, err := low.ExtractObject[*ExternalDoc](ctx, ExternalDocsLabel, root, idx)
|
||||
t.ExternalDocs = extDocs
|
||||
return err
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,15 +4,14 @@
|
||||
package low
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func TestFindItemInMap(t *testing.T) {
|
||||
@@ -1570,38 +1569,6 @@ func TestExtractMapFlat_Ref_Bad(t *testing.T) {
|
||||
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) {
|
||||
|
||||
yml := `x-bing: ding
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package low
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/index"
|
||||
"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.
|
||||
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
|
||||
}
|
||||
|
||||
@@ -112,6 +113,8 @@ type NodeReference[T any] struct {
|
||||
|
||||
// If HasReference is true, then Reference contains the original $ref value.
|
||||
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
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
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,
|
||||
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 {
|
||||
e <- err
|
||||
}
|
||||
@@ -133,7 +134,7 @@ func (d *Definitions) Hash() [32]byte {
|
||||
}
|
||||
|
||||
// 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)
|
||||
resultChan := make(chan definitionResult[*Parameter])
|
||||
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,
|
||||
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 {
|
||||
e <- err
|
||||
}
|
||||
@@ -182,7 +183,7 @@ type definitionResult[T any] struct {
|
||||
}
|
||||
|
||||
// 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)
|
||||
resultChan := make(chan definitionResult[*Response])
|
||||
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,
|
||||
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 {
|
||||
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.
|
||||
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)
|
||||
resultChan := make(chan definitionResult[*SecurityScheme])
|
||||
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,
|
||||
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 {
|
||||
e <- err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
var keyNode, currNode *yaml.Node
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(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 {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
@@ -102,11 +103,11 @@ func (i *Items) Hash() [32]byte {
|
||||
}
|
||||
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(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 {
|
||||
return iErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
@@ -36,20 +37,20 @@ type Operation struct {
|
||||
}
|
||||
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
o.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
// 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 {
|
||||
return dErr
|
||||
}
|
||||
o.ExternalDocs = extDocs
|
||||
|
||||
// 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 {
|
||||
return pErr
|
||||
}
|
||||
@@ -62,14 +63,14 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// extract responses
|
||||
respBody, respErr := low.ExtractObject[*Responses](ResponsesLabel, root, idx)
|
||||
respBody, respErr := low.ExtractObject[*Responses](ctx, ResponsesLabel, root, idx)
|
||||
if respErr != nil {
|
||||
return respErr
|
||||
}
|
||||
o.Responses = respBody
|
||||
|
||||
// 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 {
|
||||
return sErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
p.Extensions = low.ExtractExtensions(root)
|
||||
sch, sErr := base.ExtractSchema(root, idx)
|
||||
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
if sch != nil {
|
||||
p.Schema = *sch
|
||||
}
|
||||
items, iErr := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
||||
items, iErr := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||
if iErr != nil {
|
||||
return iErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(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]
|
||||
|
||||
// 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 {
|
||||
return pErr
|
||||
}
|
||||
@@ -158,7 +159,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
opErrorChan := make(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 {
|
||||
errCh <- er
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"sort"
|
||||
@@ -54,7 +55,7 @@ func (p *Paths) FindExtension(ext string) *low.ValueReference[any] {
|
||||
}
|
||||
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
p.Extensions = low.ExtractExtensions(root)
|
||||
@@ -126,7 +127,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
cNode := value.currentNode
|
||||
path := new(PathItem)
|
||||
_ = low.BuildModel(pNode, path)
|
||||
err := path.Build(cNode, pNode, idx)
|
||||
err := path.Build(ctx, cNode, pNode, idx)
|
||||
if err != nil {
|
||||
return pathBuildResult{}, err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
r.Extensions = low.ExtractExtensions(root)
|
||||
s, err := base.ExtractSchema(root, idx)
|
||||
s, err := base.ExtractSchema(ctx, root, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -56,14 +57,14 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// extract examples
|
||||
examples, expErr := low.ExtractObject[*Examples](ExamplesLabel, root, idx)
|
||||
examples, expErr := low.ExtractObject[*Examples](ctx, ExamplesLabel, root, idx)
|
||||
if expErr != nil {
|
||||
return expErr
|
||||
}
|
||||
r.Examples = examples
|
||||
|
||||
//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 {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
r.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
if utils.IsNodeMap(root) {
|
||||
codes, err := low.ExtractMapNoLookup[*Response](root, idx)
|
||||
codes, err := low.ExtractMapNoLookup[*Response](ctx, root, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
s.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(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 {
|
||||
return sErr
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
package v2
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/pb33f/libopenapi/datamodel"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"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.
|
||||
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.
|
||||
type Swagger struct {
|
||||
@@ -129,6 +130,9 @@ func CreateDocumentFromConfig(info *datamodel.SpecInfo,
|
||||
// CreateDocument will create a new Swagger document from the provided SpecInfo.
|
||||
//
|
||||
// Deprecated: Use CreateDocumentFromConfig instead.
|
||||
|
||||
// TODO; DELETE ME
|
||||
|
||||
func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) {
|
||||
return createDocument(info, &datamodel.DocumentConfiguration{
|
||||
AllowRemoteReferences: true,
|
||||
@@ -155,8 +159,10 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
||||
// build out swagger scalar variables.
|
||||
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
// 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 {
|
||||
errors = append(errors, err)
|
||||
}
|
||||
@@ -186,7 +192,7 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
||||
doneChan := make(chan bool)
|
||||
errChan := make(chan error)
|
||||
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
|
||||
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) {
|
||||
info, err := low.ExtractObject[*base.Info](base.InfoLabel, root, idx)
|
||||
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](ctx, base.InfoLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -220,8 +226,8 @@ func extractInfo(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
paths, err := low.ExtractObject[*Paths](PathsLabel, root, idx)
|
||||
func extractPaths(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
paths, err := low.ExtractObject[*Paths](ctx, PathsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -229,8 +235,8 @@ func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<-
|
||||
doc.Paths = paths
|
||||
c <- true
|
||||
}
|
||||
func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
def, err := low.ExtractObject[*Definitions](DefinitionsLabel, root, idx)
|
||||
func extractDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
def, err := low.ExtractObject[*Definitions](ctx, DefinitionsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -238,8 +244,8 @@ func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c c
|
||||
doc.Definitions = def
|
||||
c <- true
|
||||
}
|
||||
func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
param, err := low.ExtractObject[*ParameterDefinitions](ParametersLabel, root, idx)
|
||||
func extractParamDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
param, err := low.ExtractObject[*ParameterDefinitions](ctx, ParametersLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -248,8 +254,8 @@ func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
resp, err := low.ExtractObject[*ResponsesDefinitions](ResponsesLabel, root, idx)
|
||||
func extractResponsesDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
resp, err := low.ExtractObject[*ResponsesDefinitions](ctx, ResponsesLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -258,8 +264,8 @@ func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecI
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
sec, err := low.ExtractObject[*SecurityDefinitions](SecurityDefinitionsLabel, root, idx)
|
||||
func extractSecurityDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||
sec, err := low.ExtractObject[*SecurityDefinitions](ctx, SecurityDefinitionsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -268,8 +274,8 @@ func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIn
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractTags(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)
|
||||
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](ctx, base.TagsLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
@@ -282,8 +288,8 @@ func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
||||
c <- true
|
||||
}
|
||||
|
||||
func extractSecurity(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)
|
||||
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](ctx, SecurityLabel, root, idx)
|
||||
if err != nil {
|
||||
e <- err
|
||||
return
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
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-") {
|
||||
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 {
|
||||
return eErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
co.Reference = new(low.Reference)
|
||||
@@ -161,55 +162,55 @@ func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
go func() {
|
||||
schemas, err := extractComponentValues[*base.SchemaProxy](SchemasLabel, root, idx)
|
||||
schemas, err := extractComponentValues[*base.SchemaProxy](ctx, SchemasLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Schemas = schemas
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
parameters, err := extractComponentValues[*Parameter](ParametersLabel, root, idx)
|
||||
parameters, err := extractComponentValues[*Parameter](ctx, ParametersLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Parameters = parameters
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
responses, err := extractComponentValues[*Response](ResponsesLabel, root, idx)
|
||||
responses, err := extractComponentValues[*Response](ctx, ResponsesLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Responses = responses
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
examples, err := extractComponentValues[*base.Example](base.ExamplesLabel, root, idx)
|
||||
examples, err := extractComponentValues[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Examples = examples
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
requestBodies, err := extractComponentValues[*RequestBody](RequestBodiesLabel, root, idx)
|
||||
requestBodies, err := extractComponentValues[*RequestBody](ctx, RequestBodiesLabel, root, idx)
|
||||
captureError(err)
|
||||
co.RequestBodies = requestBodies
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
headers, err := extractComponentValues[*Header](HeadersLabel, root, idx)
|
||||
headers, err := extractComponentValues[*Header](ctx, HeadersLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Headers = headers
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
securitySchemes, err := extractComponentValues[*SecurityScheme](SecuritySchemesLabel, root, idx)
|
||||
securitySchemes, err := extractComponentValues[*SecurityScheme](ctx, SecuritySchemesLabel, root, idx)
|
||||
captureError(err)
|
||||
co.SecuritySchemes = securitySchemes
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
links, err := extractComponentValues[*Link](LinksLabel, root, idx)
|
||||
links, err := extractComponentValues[*Link](ctx, LinksLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Links = links
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
callbacks, err := extractComponentValues[*Callback](CallbacksLabel, root, idx)
|
||||
callbacks, err := extractComponentValues[*Callback](ctx, CallbacksLabel, root, idx)
|
||||
captureError(err)
|
||||
co.Callbacks = callbacks
|
||||
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
|
||||
// low level model.
|
||||
// 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]]
|
||||
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
||||
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
|
||||
var err error
|
||||
if h, _, _ := utils.IsNodeRefValue(node); h && label != SchemasLabel {
|
||||
node, err = low.LocateRefNode(node, idx)
|
||||
node, _, err = low.LocateRefNode(node, idx)
|
||||
}
|
||||
if err != nil {
|
||||
return componentBuildResult[T]{}, err
|
||||
@@ -296,7 +297,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
||||
|
||||
// build.
|
||||
_ = low.BuildModel(node, n)
|
||||
err = n.Build(currentLabel, node, idx)
|
||||
err = n.Build(ctx, currentLabel, node, idx)
|
||||
if err != nil {
|
||||
return componentBuildResult[T]{}, err
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"os"
|
||||
"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}
|
||||
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
|
||||
|
||||
// create an index config and shadow the document configuration.
|
||||
idxConfig := index.CreateOpenAPIIndexConfig()
|
||||
idxConfig.SpecInfo = info
|
||||
idxConfig.BasePath = cwd
|
||||
idxConfig.IgnoreArrayCircularReferences = config.IgnoreArrayCircularReferences
|
||||
idxConfig.IgnorePolymorphicCircularReferences = config.IgnorePolymorphicCircularReferences
|
||||
idxConfig.AvoidCircularReferenceCheck = config.SkipCircularReferenceCheck
|
||||
|
||||
idxConfig.AvoidCircularReferenceCheck = true
|
||||
idxConfig.BaseURL = config.BaseURL
|
||||
idxConfig.BasePath = config.BasePath
|
||||
rolodex := index.NewRolodex(idxConfig)
|
||||
rolodex.SetRootNode(info.RootNode)
|
||||
doc.Rolodex = rolodex
|
||||
|
||||
// If basePath is provided override it
|
||||
if config.BasePath != "" {
|
||||
// If basePath is provided, add a local filesystem to the rolodex.
|
||||
if idxConfig.BasePath != "" {
|
||||
var absError error
|
||||
var cwd string
|
||||
cwd, absError = filepath.Abs(config.BasePath)
|
||||
if absError != nil {
|
||||
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
|
||||
err := rolodex.IndexTheRolodex()
|
||||
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()
|
||||
@@ -125,17 +143,17 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
||||
}
|
||||
}
|
||||
|
||||
runExtraction := func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||
runExtraction := func(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||
runFunc func(ctx context.Context, i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||
ers *[]error,
|
||||
wg *sync.WaitGroup,
|
||||
) {
|
||||
if er := runFunc(info, doc, idx); er != nil {
|
||||
if er := runFunc(ctx, info, doc, idx); er != nil {
|
||||
*ers = append(*ers, er)
|
||||
}
|
||||
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,
|
||||
extractServers,
|
||||
extractTags,
|
||||
@@ -146,28 +164,30 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
||||
extractWebhooks,
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
wg.Add(len(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()
|
||||
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)
|
||||
if vn != nil {
|
||||
ir := base.Info{}
|
||||
_ = 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}
|
||||
doc.Info = nr
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, info.RootNode.Content[0], idx)
|
||||
func extractSecurity(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, info.RootNode.Content[0], idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -181,8 +201,8 @@ func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInd
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
||||
func extractExternalDocs(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
||||
if dErr != nil {
|
||||
return dErr
|
||||
}
|
||||
@@ -190,12 +210,12 @@ func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.Spe
|
||||
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)
|
||||
if vn != nil {
|
||||
ir := Components{}
|
||||
_ = low.BuildModel(vn, &ir)
|
||||
err := ir.Build(vn, idx)
|
||||
err := ir.Build(ctx, vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -205,7 +225,7 @@ func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecI
|
||||
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)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
@@ -214,7 +234,7 @@ func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInde
|
||||
if utils.IsNodeMap(srvN) {
|
||||
srvr := Server{}
|
||||
_ = low.BuildModel(srvN, &srvr)
|
||||
_ = srvr.Build(ln, srvN, idx)
|
||||
_ = srvr.Build(ctx, ln, srvN, idx)
|
||||
servers = append(servers, low.ValueReference[*Server]{
|
||||
Value: &srvr,
|
||||
ValueNode: srvN,
|
||||
@@ -231,7 +251,7 @@ func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInde
|
||||
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)
|
||||
if vn != nil {
|
||||
if utils.IsNodeArray(vn) {
|
||||
@@ -240,7 +260,7 @@ func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
||||
if utils.IsNodeMap(tagN) {
|
||||
tag := base.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
|
||||
}
|
||||
tags = append(tags, low.ValueReference[*base.Tag]{
|
||||
@@ -259,11 +279,11 @@ func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
||||
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)
|
||||
if vn != nil {
|
||||
ir := Paths{}
|
||||
err := ir.Build(ln, vn, idx)
|
||||
err := ir.Build(ctx, ln, vn, idx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -273,8 +293,8 @@ func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
||||
return nil
|
||||
}
|
||||
|
||||
func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](WebhooksLabel, info.RootNode, idx)
|
||||
func extractWebhooks(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](ctx, WebhooksLabel, info.RootNode, idx)
|
||||
if eErr != nil {
|
||||
return eErr
|
||||
}
|
||||
|
||||
@@ -147,9 +147,8 @@ func TestCreateDocumentStripe(t *testing.T) {
|
||||
d, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||
AllowFileReferences: 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, "Stripe API", d.Info.Value.Title.Value)
|
||||
@@ -206,7 +205,8 @@ func TestCreateDocument_WebHooks(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
||||
yml := `webhooks:
|
||||
yml := `openapi: 3.0
|
||||
webhooks:
|
||||
$ref: #bork`
|
||||
|
||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||
@@ -215,7 +215,7 @@ func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
||||
AllowFileReferences: false,
|
||||
AllowRemoteReferences: false,
|
||||
})
|
||||
assert.Len(t, err, 1)
|
||||
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||
}
|
||||
|
||||
func TestCreateDocument_Servers(t *testing.T) {
|
||||
@@ -613,7 +613,7 @@ webhooks:
|
||||
AllowFileReferences: 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())
|
||||
}
|
||||
|
||||
@@ -630,7 +630,7 @@ components:
|
||||
AllowFileReferences: 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) {
|
||||
@@ -661,7 +661,7 @@ tags:
|
||||
AllowRemoteReferences: false,
|
||||
})
|
||||
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) {
|
||||
@@ -676,7 +676,7 @@ security:
|
||||
AllowRemoteReferences: false,
|
||||
})
|
||||
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())
|
||||
}
|
||||
|
||||
@@ -691,7 +691,7 @@ externalDocs:
|
||||
AllowFileReferences: 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) {
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
h.Reference = new(low.Reference)
|
||||
@@ -108,7 +109,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return eErr
|
||||
}
|
||||
@@ -121,7 +122,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// handle schema
|
||||
sch, sErr := base.ExtractSchema(root, idx)
|
||||
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
@@ -130,7 +131,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return cErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
l.Reference = new(low.Reference)
|
||||
l.Extensions = low.ExtractExtensions(root)
|
||||
// extract server.
|
||||
ser, sErr := low.ExtractObject[*Server](ServerLabel, root, idx)
|
||||
ser, sErr := low.ExtractObject[*Server](ctx, ServerLabel, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
mt.Reference = new(low.Reference)
|
||||
@@ -83,7 +84,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
//handle schema
|
||||
sch, sErr := base.ExtractSchema(root, idx)
|
||||
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
@@ -92,7 +93,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return eErr
|
||||
}
|
||||
@@ -105,7 +106,7 @@ func (mt *MediaType) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return encErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
o.Reference = new(low.Reference)
|
||||
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 {
|
||||
return vErr
|
||||
}
|
||||
o.Implicit = v
|
||||
|
||||
v, vErr = low.ExtractObject[*OAuthFlow](PasswordLabel, root, idx)
|
||||
v, vErr = low.ExtractObject[*OAuthFlow](ctx, PasswordLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
o.Password = v
|
||||
|
||||
v, vErr = low.ExtractObject[*OAuthFlow](ClientCredentialsLabel, root, idx)
|
||||
v, vErr = low.ExtractObject[*OAuthFlow](ctx, ClientCredentialsLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
o.ClientCredentials = v
|
||||
|
||||
v, vErr = low.ExtractObject[*OAuthFlow](AuthorizationCodeLabel, root, idx)
|
||||
v, vErr = low.ExtractObject[*OAuthFlow](ctx, AuthorizationCodeLabel, root, idx)
|
||||
if vErr != nil {
|
||||
return vErr
|
||||
}
|
||||
@@ -116,7 +117,7 @@ func (o *OAuthFlow) FindExtension(ext string) *low.ValueReference[any] {
|
||||
}
|
||||
|
||||
// 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.Extensions = low.ExtractExtensions(root)
|
||||
return nil
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
o.Reference = new(low.Reference)
|
||||
o.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
// 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 {
|
||||
return dErr
|
||||
}
|
||||
o.ExternalDocs = extDocs
|
||||
|
||||
// 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 {
|
||||
return pErr
|
||||
}
|
||||
@@ -82,21 +83,21 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// extract request body
|
||||
rBody, rErr := low.ExtractObject[*RequestBody](RequestBodyLabel, root, idx)
|
||||
rBody, rErr := low.ExtractObject[*RequestBody](ctx, RequestBodyLabel, root, idx)
|
||||
if rErr != nil {
|
||||
return rErr
|
||||
}
|
||||
o.RequestBody = rBody
|
||||
|
||||
// extract responses
|
||||
respBody, respErr := low.ExtractObject[*Responses](ResponsesLabel, root, idx)
|
||||
respBody, respErr := low.ExtractObject[*Responses](ctx, ResponsesLabel, root, idx)
|
||||
if respErr != nil {
|
||||
return respErr
|
||||
}
|
||||
o.Responses = respBody
|
||||
|
||||
// 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 {
|
||||
return cbErr
|
||||
}
|
||||
@@ -109,7 +110,7 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return sErr
|
||||
}
|
||||
@@ -134,7 +135,7 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return serErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
p.Reference = new(low.Reference)
|
||||
@@ -71,7 +72,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// handle schema
|
||||
sch, sErr := base.ExtractSchema(root, idx)
|
||||
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||
if sErr != nil {
|
||||
return sErr
|
||||
}
|
||||
@@ -80,7 +81,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return eErr
|
||||
}
|
||||
@@ -93,7 +94,7 @@ func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return cErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
// 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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
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]
|
||||
|
||||
// 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 {
|
||||
return pErr
|
||||
}
|
||||
@@ -143,7 +144,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
if utils.IsNodeMap(srvN) {
|
||||
srvr := new(Server)
|
||||
_ = low.BuildModel(srvN, srvr)
|
||||
srvr.Build(ln, srvN, idx)
|
||||
srvr.Build(ctx, ln, srvN, idx)
|
||||
servers = append(servers, low.ValueReference[*Server]{
|
||||
Value: srvr,
|
||||
ValueNode: srvN,
|
||||
@@ -198,6 +199,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
continue // ignore everything else.
|
||||
}
|
||||
|
||||
foundContext := ctx
|
||||
var op Operation
|
||||
opIsRef := false
|
||||
var opRefVal string
|
||||
@@ -213,12 +215,15 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
|
||||
opIsRef = true
|
||||
opRefVal = ref
|
||||
r, err := low.LocateRefNode(pathNode, idx)
|
||||
r, newIdx, err, nCtx := low.LocateRefNodeWithContext(ctx, pathNode, idx)
|
||||
if r != nil {
|
||||
if r.Kind == yaml.DocumentNode {
|
||||
r = r.Content[0]
|
||||
}
|
||||
pathNode = r
|
||||
foundContext = nCtx
|
||||
foundContext = context.WithValue(foundContext, "foundIndex", newIdx)
|
||||
|
||||
if r.Tag == "" {
|
||||
// If it's a node from file, tag is empty
|
||||
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",
|
||||
pathNode.Content[1].Value, pathNode.Content[1].Line, pathNode.Content[1].Column)
|
||||
}
|
||||
} else {
|
||||
foundContext = context.WithValue(foundContext, "foundIndex", idx)
|
||||
}
|
||||
wg.Add(1)
|
||||
low.BuildModelAsync(pathNode, &op, &wg, &errors)
|
||||
@@ -241,6 +248,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
Value: &op,
|
||||
KeyNode: currentNode,
|
||||
ValueNode: pathNode,
|
||||
Context: foundContext,
|
||||
}
|
||||
if opIsRef {
|
||||
opRef.Reference = opRefVal
|
||||
@@ -277,7 +285,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
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 != "" {
|
||||
op.Value.Reference.Reference = ref
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
p.Reference = new(low.Reference)
|
||||
@@ -134,7 +135,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
cNode := value.currentNode
|
||||
|
||||
if ok, _, _ := utils.IsNodeRefValue(pNode); ok {
|
||||
r, err := low.LocateRefNode(pNode, idx)
|
||||
r, _, err := low.LocateRefNode(pNode, idx)
|
||||
if r != nil {
|
||||
pNode = r
|
||||
if r.Tag == "" {
|
||||
@@ -156,9 +157,12 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
|
||||
path := new(PathItem)
|
||||
_ = 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 {
|
||||
return buildResult{}, err
|
||||
//return buildResult{}, err
|
||||
idx.GetLogger().Error(fmt.Sprintf("error building path item '%s'", err.Error()))
|
||||
}
|
||||
|
||||
return buildResult{
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
rb.Reference = new(low.Reference)
|
||||
rb.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
// 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 {
|
||||
return cErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
r.Reference = new(low.Reference)
|
||||
r.Extensions = low.ExtractExtensions(root)
|
||||
|
||||
//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 {
|
||||
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 {
|
||||
return cErr
|
||||
}
|
||||
@@ -86,7 +87,7 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return lErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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
|
||||
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)
|
||||
r.Reference = new(low.Reference)
|
||||
r.Extensions = low.ExtractExtensions(root)
|
||||
utils.CheckForMergeNodes(root)
|
||||
if utils.IsNodeMap(root) {
|
||||
codes, err := low.ExtractMapNoLookup[*Response](root, idx)
|
||||
codes, err := low.ExtractMapNoLookup[*Response](ctx, root, idx)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"fmt"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
ss.Reference = new(low.Reference)
|
||||
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 {
|
||||
return oaErr
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
package v3
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"github.com/pb33f/libopenapi/datamodel/low"
|
||||
"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.
|
||||
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)
|
||||
utils.CheckForMergeNodes(root)
|
||||
s.Reference = new(low.Reference)
|
||||
|
||||
@@ -64,6 +64,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
Definition: definitionPath,
|
||||
Node: node.Content[i+1],
|
||||
Path: jsonPath,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
isRef, _, _ := utils.IsNodeRefValue(node.Content[i+1])
|
||||
@@ -120,6 +121,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
Definition: definitionPath,
|
||||
Node: prop,
|
||||
Path: jsonPath,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
isRef, _, _ := utils.IsNodeRefValue(prop)
|
||||
@@ -165,6 +167,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
Definition: definitionPath,
|
||||
Node: element,
|
||||
Path: jsonPath,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
isRef, _, _ := utils.IsNodeRefValue(element)
|
||||
@@ -341,6 +344,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
Name: name,
|
||||
Node: node,
|
||||
Path: p,
|
||||
Index: index,
|
||||
}
|
||||
|
||||
// add to raw sequenced refs
|
||||
@@ -367,6 +371,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
Name: ref.Name,
|
||||
Node: &copiedNode,
|
||||
Path: p,
|
||||
Index: index,
|
||||
}
|
||||
// protect this data using a copy, prevent the resolver from destroying things.
|
||||
index.refsWithSiblings[value] = copied
|
||||
@@ -592,6 +597,11 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
||||
locate := func(ref *Reference, refIndex int, sequence []*ReferenceMapped) {
|
||||
located := index.FindComponent(ref.FullDefinition, ref.Node)
|
||||
if located != nil {
|
||||
|
||||
if located.Index == nil {
|
||||
index.logger.Warn("located component has no index", "component", located.FullDefinition)
|
||||
}
|
||||
|
||||
index.refLock.Lock()
|
||||
// have we already mapped this?
|
||||
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.
|
||||
if strings.Contains(componentId, "%") {
|
||||
// decode the url.
|
||||
@@ -72,6 +72,12 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string) *Refer
|
||||
|
||||
fullDef := fmt.Sprintf("%s%s", absoluteFilePath, componentId)
|
||||
|
||||
// TODO: clean this shit up
|
||||
|
||||
newIndexWithUpdatedPath := *index
|
||||
newIndexWithUpdatedPath.specAbsolutePath = absoluteFilePath
|
||||
newIndexWithUpdatedPath.AbsoluteFile = absoluteFilePath
|
||||
|
||||
// extract properties
|
||||
ref := &Reference{
|
||||
FullDefinition: fullDef,
|
||||
@@ -79,6 +85,8 @@ func FindComponent(root *yaml.Node, componentId, absoluteFilePath string) *Refer
|
||||
Name: name,
|
||||
Node: resNode,
|
||||
Path: friendlySearch,
|
||||
RemoteLocation: absoluteFilePath,
|
||||
Index: &newIndexWithUpdatedPath,
|
||||
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 {
|
||||
if index.root != nil {
|
||||
return FindComponent(index.root, componentId, index.specAbsolutePath)
|
||||
return FindComponent(index.root, componentId, index.specAbsolutePath, index)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -139,6 +147,9 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
||||
|
||||
var parsedDocument *yaml.Node
|
||||
var err error
|
||||
|
||||
idx := index
|
||||
|
||||
if ext != "" {
|
||||
|
||||
// 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)
|
||||
return nil
|
||||
}
|
||||
if rFile.GetIndex() != nil {
|
||||
idx = rFile.GetIndex()
|
||||
}
|
||||
|
||||
parsedDocument, err = rFile.GetContentAsYAMLNode()
|
||||
if err != nil {
|
||||
@@ -184,6 +198,7 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
||||
FullDefinition: absoluteFileLocation,
|
||||
Definition: fileName,
|
||||
Name: fileName,
|
||||
Index: idx,
|
||||
Node: parsedDocument,
|
||||
IsRemote: true,
|
||||
RemoteLocation: absoluteFileLocation,
|
||||
@@ -192,7 +207,7 @@ func (index *SpecIndex) lookupRolodex(uri []string) *Reference {
|
||||
}
|
||||
return foundRef
|
||||
} else {
|
||||
foundRef = FindComponent(parsedDocument, query, absoluteFileLocation)
|
||||
foundRef = FindComponent(parsedDocument, query, absoluteFileLocation, index)
|
||||
if foundRef != nil {
|
||||
foundRef.IsRemote = true
|
||||
foundRef.RemoteLocation = absoluteFileLocation
|
||||
|
||||
@@ -61,9 +61,14 @@ func TestSpecIndex_CheckCircularIndex(t *testing.T) {
|
||||
index := rolo.GetRootIndex()
|
||||
|
||||
assert.Nil(t, index.uri)
|
||||
assert.NotNil(t, index.SearchIndexForReference("second.yaml#/properties/property2"))
|
||||
assert.NotNil(t, index.SearchIndexForReference("second.yaml"))
|
||||
assert.Nil(t, index.SearchIndexForReference("fourth.yaml"))
|
||||
|
||||
a, _ := index.SearchIndexForReference("second.yaml#/properties/property2")
|
||||
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) {
|
||||
|
||||
@@ -35,6 +35,7 @@ type Reference struct {
|
||||
Circular bool
|
||||
Seen bool
|
||||
IsRemote bool
|
||||
Index *SpecIndex // index that contains this reference.
|
||||
RemoteLocation string
|
||||
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
|
||||
@@ -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,
|
||||
// everything is pre-walked if you need it.
|
||||
type SpecIndex struct {
|
||||
specAbsolutePath string
|
||||
AbsoluteFile string
|
||||
rolodex *Rolodex // the rolodex is used to fetch remote and file based documents.
|
||||
allRefs map[string]*Reference // all (deduplicated) refs
|
||||
rawSequencedRefs []*Reference // all raw references in sequence as they are scanned, not deduped.
|
||||
@@ -261,7 +264,6 @@ type SpecIndex struct {
|
||||
httpClient *http.Client
|
||||
componentIndexChan chan bool
|
||||
polyComponentIndexChan chan bool
|
||||
specAbsolutePath string
|
||||
resolver *Resolver
|
||||
cache syncmap.Map
|
||||
built bool
|
||||
|
||||
@@ -267,7 +267,7 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
||||
if j.FullDefinition == r.FullDefinition {
|
||||
|
||||
var foundDup *Reference
|
||||
foundRef := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||
foundRef, _ := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||
if foundRef != nil {
|
||||
foundDup = foundRef
|
||||
}
|
||||
@@ -307,7 +307,7 @@ func (resolver *Resolver) VisitReference(ref *Reference, seen map[string]bool, j
|
||||
|
||||
if !skip {
|
||||
var original *Reference
|
||||
foundRef := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||
foundRef, _ := resolver.specIndex.SearchIndexForReferenceByReference(r)
|
||||
if foundRef != nil {
|
||||
original = foundRef
|
||||
}
|
||||
@@ -335,7 +335,7 @@ func (resolver *Resolver) isInfiniteCircularDependency(ref *Reference, visitedDe
|
||||
}
|
||||
|
||||
for refDefinition := range ref.RequiredRefProperties {
|
||||
r := resolver.specIndex.SearchIndexForReference(refDefinition)
|
||||
r, _ := resolver.specIndex.SearchIndexForReference(refDefinition)
|
||||
if initialRef != nil && initialRef.Definition == r.Definition {
|
||||
return true, visitedDefinitions
|
||||
}
|
||||
@@ -497,7 +497,7 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
||||
IsRemote: true,
|
||||
}
|
||||
|
||||
locatedRef = resolver.specIndex.SearchIndexForReferenceByReference(searchRef)
|
||||
locatedRef, _ = resolver.specIndex.SearchIndexForReferenceByReference(searchRef)
|
||||
|
||||
if locatedRef == nil {
|
||||
_, path := utils.ConvertComponentIdIntoFriendlyPathSearch(value)
|
||||
|
||||
@@ -596,7 +596,7 @@ func TestResolver_ResolveComponents_MixedRef(t *testing.T) {
|
||||
resolver := index().GetResolver()
|
||||
|
||||
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.
|
||||
assert.Equal(t, 6, resolver.GetRelativesSeen())
|
||||
|
||||
@@ -87,6 +87,7 @@ func (l *LocalFile) Index(config *SpecIndexConfig) (*SpecIndex, error) {
|
||||
|
||||
index := NewSpecIndexWithConfig(info.RootNode, config)
|
||||
index.specAbsolutePath = l.fullPath
|
||||
|
||||
l.index = index
|
||||
return index, nil
|
||||
|
||||
|
||||
@@ -176,13 +176,10 @@ const (
|
||||
|
||||
func NewRemoteFSWithConfig(specIndexConfig *SpecIndexConfig) (*RemoteFS, error) {
|
||||
remoteRootURL := specIndexConfig.BaseURL
|
||||
|
||||
// TODO: handle logging
|
||||
|
||||
log := specIndexConfig.Logger
|
||||
if log == nil {
|
||||
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
|
||||
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))
|
||||
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()
|
||||
idx, idxError := remoteFile.Index(&copiedCfg)
|
||||
|
||||
i.Files.Store(absolutePath, remoteFile)
|
||||
|
||||
if len(remoteFile.data) > 0 {
|
||||
i.logger.Debug("successfully loaded file", "file", absolutePath)
|
||||
}
|
||||
@@ -390,6 +385,7 @@ func (i *RemoteFS) Open(remoteURL string) (fs.File, error) {
|
||||
|
||||
// remove from processing
|
||||
i.ProcessingFiles.Delete(remoteParsedURL.Path)
|
||||
i.Files.Store(absolutePath, remoteFile)
|
||||
|
||||
//if !i.remoteRunning {
|
||||
return remoteFile, errors.Join(i.remoteErrors...)
|
||||
|
||||
@@ -4,130 +4,151 @@
|
||||
package index
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) *Reference {
|
||||
type ContextKey string
|
||||
|
||||
if v, ok := index.cache.Load(fullRef); ok {
|
||||
return v.(*Reference)
|
||||
}
|
||||
const CurrentPathKey ContextKey = "currentPath"
|
||||
|
||||
ref := fullRef.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 = 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
|
||||
func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) (*Reference, *SpecIndex) {
|
||||
r, idx, _ := index.SearchIndexForReferenceByReferenceWithContext(context.Background(), fullRef)
|
||||
return r, idx
|
||||
}
|
||||
|
||||
// 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
|
||||
// extracted when parsing the OpenAPI Spec.
|
||||
func (index *SpecIndex) SearchIndexForReference(ref string) *Reference {
|
||||
return index.SearchIndexForReferenceByReference(&Reference{FullDefinition: ref})
|
||||
func (index *SpecIndex) SearchIndexForReference(ref string) (*Reference, *SpecIndex) {
|
||||
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()
|
||||
idx := NewSpecIndexWithConfig(&rootNode, c)
|
||||
|
||||
ref := idx.SearchIndexForReference("#/components/schemas/Pet")
|
||||
ref, _ := idx.SearchIndexForReference("#/components/schemas/Pet")
|
||||
assert.NotNil(t, ref)
|
||||
}
|
||||
|
||||
@@ -149,6 +149,14 @@ func (index *SpecIndex) BuildIndex() {
|
||||
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.
|
||||
func (index *SpecIndex) GetRootNode() *yaml.Node {
|
||||
return index.root
|
||||
|
||||
@@ -949,7 +949,7 @@ func TestSpecIndex_lookupFileReference_MultiRes(t *testing.T) {
|
||||
index := rolo.GetRootIndex()
|
||||
//index.seenRemoteSources = make(map[string]*yaml.Node)
|
||||
absoluteRef, _ := filepath.Abs("embie.yaml#/naughty")
|
||||
fRef := index.SearchIndexForReference(absoluteRef)
|
||||
fRef, _ := index.SearchIndexForReference(absoluteRef)
|
||||
assert.NotNil(t, fRef)
|
||||
|
||||
}
|
||||
|
||||
@@ -347,7 +347,7 @@ func (index *SpecIndex) scanOperationParams(params []*yaml.Node, pathItemNode *y
|
||||
paramRef := index.allMappedRefs[paramRefName]
|
||||
if paramRef == nil {
|
||||
// could be in the rolodex
|
||||
ref := index.SearchIndexForReference(paramRefName)
|
||||
ref, _ := index.SearchIndexForReference(paramRefName)
|
||||
if ref != nil {
|
||||
paramRef = ref
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user