mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
Merge branch 'main' into Baliedge/PIP-2552-consistent-ordering
This commit is contained in:
BIN
.github/sponsors/scalar-dark.png
vendored
Normal file
BIN
.github/sponsors/scalar-dark.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 302 KiB |
BIN
.github/sponsors/scalar-light.png
vendored
Normal file
BIN
.github/sponsors/scalar-light.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 312 KiB |
2
.github/workflows/build.yaml
vendored
2
.github/workflows/build.yaml
vendored
@@ -16,7 +16,7 @@ jobs:
|
|||||||
- name: Set up Go 1.x
|
- name: Set up Go 1.x
|
||||||
uses: actions/setup-go@v3
|
uses: actions/setup-go@v3
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: 1.21
|
||||||
id: go
|
id: go
|
||||||
|
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
|
|||||||
14
README.md
14
README.md
@@ -29,6 +29,17 @@ like our _very kind_ sponsors:
|
|||||||
|
|
||||||
[Speakeasy](https://speakeasyapi.dev/?utm_source=libopenapi+repo&utm_medium=github+sponsorship)
|
[Speakeasy](https://speakeasyapi.dev/?utm_source=libopenapi+repo&utm_medium=github+sponsorship)
|
||||||
|
|
||||||
|
<a href="https://scalar.com">
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset=".github/sponsors/scalar-dark.png">
|
||||||
|
<img alt="scalar'" src=".github/sponsors/scalar-light.png">
|
||||||
|
</picture>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
[scalar](https://scalar.com)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
`libopenapi` is pretty new, so our list of notable projects that depend on `libopenapi` is small (let me know if you'd like to add your project)
|
`libopenapi` is pretty new, so our list of notable projects that depend on `libopenapi` is small (let me know if you'd like to add your project)
|
||||||
@@ -39,7 +50,7 @@ like our _very kind_ sponsors:
|
|||||||
- [github.com/danielgtaylor/restish](https://github.com/danielgtaylor/restish) - "Restish is a CLI for interacting with REST-ish HTTP APIs"
|
- [github.com/danielgtaylor/restish](https://github.com/danielgtaylor/restish) - "Restish is a CLI for interacting with REST-ish HTTP APIs"
|
||||||
- [github.com/speakeasy-api/speakeasy](https://github.com/speakeasy-api/speakeasy) - "Speakeasy CLI makes validating OpenAPI docs and generating idiomatic SDKs easy!"
|
- [github.com/speakeasy-api/speakeasy](https://github.com/speakeasy-api/speakeasy) - "Speakeasy CLI makes validating OpenAPI docs and generating idiomatic SDKs easy!"
|
||||||
- [github.com/apicat/apicat](https://github.com/apicat/apicat) - "AI-powered API development tool"
|
- [github.com/apicat/apicat](https://github.com/apicat/apicat) - "AI-powered API development tool"
|
||||||
- [github.com/mattermost/mattermost](https://github.com/mattermost/mattermost) = "Software development lifecycle platform"
|
- [github.com/mattermost/mattermost](https://github.com/mattermost/mattermost) - "Software development lifecycle platform"
|
||||||
- Your project here?
|
- Your project here?
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -67,6 +78,7 @@ See all the documentation at https://pb33f.io/libopenapi/
|
|||||||
- [Using Vendor Extensions](https://pb33f.io/libopenapi/extensions/)
|
- [Using Vendor Extensions](https://pb33f.io/libopenapi/extensions/)
|
||||||
- [The Index](https://pb33f.io/libopenapi/index/)
|
- [The Index](https://pb33f.io/libopenapi/index/)
|
||||||
- [The Resolver](https://pb33f.io/libopenapi/resolver/)
|
- [The Resolver](https://pb33f.io/libopenapi/resolver/)
|
||||||
|
- [The Rolodex](https://pb33f.io/libopenapi/rolodex/)
|
||||||
- [Circular References](https://pb33f.io/libopenapi/circular-references/)
|
- [Circular References](https://pb33f.io/libopenapi/circular-references/)
|
||||||
- [What Changed / Diff Engine](https://pb33f.io/libopenapi/what-changed/)
|
- [What Changed / Diff Engine](https://pb33f.io/libopenapi/what-changed/)
|
||||||
- [FAQ](https://pb33f.io/libopenapi/faq/)
|
- [FAQ](https://pb33f.io/libopenapi/faq/)
|
||||||
|
|||||||
@@ -4,8 +4,11 @@
|
|||||||
package datamodel
|
package datamodel
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"io/fs"
|
||||||
|
"log/slog"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"os"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DocumentConfiguration is used to configure the document creation process. It was added in v0.6.0 to allow
|
// DocumentConfiguration is used to configure the document creation process. It was added in v0.6.0 to allow
|
||||||
@@ -20,17 +23,54 @@ type DocumentConfiguration struct {
|
|||||||
|
|
||||||
// RemoteURLHandler is a function that will be used to retrieve remote documents. If not set, the default
|
// RemoteURLHandler is a function that will be used to retrieve remote documents. If not set, the default
|
||||||
// remote document getter will be used.
|
// remote document getter will be used.
|
||||||
|
//
|
||||||
|
// The remote handler is only used if the BaseURL is set. If the BaseURL is not set, then the remote handler
|
||||||
|
// will not be used, as there will be nothing to use it against.
|
||||||
|
//
|
||||||
// Resolves [#132]: https://github.com/pb33f/libopenapi/issues/132
|
// Resolves [#132]: https://github.com/pb33f/libopenapi/issues/132
|
||||||
RemoteURLHandler func(url string) (*http.Response, error)
|
RemoteURLHandler utils.RemoteURLHandler
|
||||||
|
|
||||||
// If resolving locally, the BasePath will be the root from which relative references will be resolved from.
|
// If resolving locally, the BasePath will be the root from which relative references will be resolved from.
|
||||||
// It's usually the location of the root specification.
|
// It's usually the location of the root specification.
|
||||||
|
//
|
||||||
|
// Be warned, setting this value will instruct the rolodex to index EVERY yaml and JSON file it finds from the
|
||||||
|
// base path. The rolodex will recurse into every directory and pick up everything form this location down.
|
||||||
|
//
|
||||||
|
// To avoid sucking in all the files, set the FileFilter to a list of specific files to be included.
|
||||||
BasePath string // set the Base Path for resolving relative references if the spec is exploded.
|
BasePath string // set the Base Path for resolving relative references if the spec is exploded.
|
||||||
|
|
||||||
|
// FileFilter is a list of specific files to be included by the rolodex when looking up references. If this value
|
||||||
|
// is set, then only these specific files will be included. If this value is not set, then all files will be included.
|
||||||
|
FileFilter []string
|
||||||
|
|
||||||
|
// RemoteFS is a filesystem that will be used to retrieve remote documents. If not set, then the rolodex will
|
||||||
|
// use its own internal remote filesystem implementation. The RemoteURLHandler will be used to retrieve remote
|
||||||
|
// documents if it has been set. The default is to use the internal remote filesystem loader.
|
||||||
|
RemoteFS fs.FS
|
||||||
|
|
||||||
|
// LocalFS is a filesystem that will be used to retrieve local documents. If not set, then the rolodex will
|
||||||
|
// use its own internal local filesystem implementation. The default is to use the internal local filesystem loader.
|
||||||
|
LocalFS fs.FS
|
||||||
|
|
||||||
// AllowFileReferences will allow the index to locate relative file references. This is disabled by default.
|
// AllowFileReferences will allow the index to locate relative file references. This is disabled by default.
|
||||||
|
//
|
||||||
|
// This behavior is now driven by the inclusion of a BasePath. If a BasePath is set, then the
|
||||||
|
// rolodex will look for relative file references. If no BasePath is set, then the rolodex will not look for
|
||||||
|
// relative file references.
|
||||||
|
//
|
||||||
|
// This value when set, will force the creation of a local file system even when the BasePath has not been set.
|
||||||
|
// it will suck in and index everything from the current working directory, down... so be warned
|
||||||
|
// FileFilter should be used to limit the scope of the rolodex.
|
||||||
AllowFileReferences bool
|
AllowFileReferences bool
|
||||||
|
|
||||||
// AllowRemoteReferences will allow the index to lookup remote references. This is disabled by default.
|
// AllowRemoteReferences will allow the index to lookup remote references. This is disabled by default.
|
||||||
|
//
|
||||||
|
// This behavior is now driven by the inclusion of a BaseURL. If a BaseURL is set, then the
|
||||||
|
// rolodex will look for remote references. If no BaseURL is set, then the rolodex will not look for
|
||||||
|
// remote references. This value has no effect as of version 0.13.0 and will be removed in a future release.
|
||||||
|
//
|
||||||
|
// This value when set, will force the creation of a remote file system even when the BaseURL has not been set.
|
||||||
|
// it will suck in every http link it finds, and recurse through all references located in each document.
|
||||||
AllowRemoteReferences bool
|
AllowRemoteReferences bool
|
||||||
|
|
||||||
// AvoidIndexBuild will avoid building the index. This is disabled by default, only use if you are sure you don't need it.
|
// AvoidIndexBuild will avoid building the index. This is disabled by default, only use if you are sure you don't need it.
|
||||||
@@ -52,18 +92,21 @@ type DocumentConfiguration struct {
|
|||||||
// So if libopenapi is returning circular references for this use case, then this option should be enabled.
|
// So if libopenapi is returning circular references for this use case, then this option should be enabled.
|
||||||
// this is disabled by default, which means array circular references will be checked.
|
// this is disabled by default, which means array circular references will be checked.
|
||||||
IgnoreArrayCircularReferences bool
|
IgnoreArrayCircularReferences bool
|
||||||
|
|
||||||
|
// SkipCircularReferenceCheck will skip over checking for circular references. This is disabled by default, which
|
||||||
|
// means circular references will be checked. This is useful for developers building out models that should be
|
||||||
|
// indexed later on.
|
||||||
|
SkipCircularReferenceCheck bool
|
||||||
|
|
||||||
|
// Logger is a structured logger that will be used for logging errors and warnings. If not set, a default logger
|
||||||
|
// will be used, set to the Error level.
|
||||||
|
Logger *slog.Logger
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOpenDocumentConfiguration() *DocumentConfiguration {
|
func NewDocumentConfiguration() *DocumentConfiguration {
|
||||||
return &DocumentConfiguration{
|
return &DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
Logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
AllowRemoteReferences: true,
|
Level: slog.LevelError,
|
||||||
}
|
})),
|
||||||
}
|
|
||||||
|
|
||||||
func NewClosedDocumentConfiguration() *DocumentConfiguration {
|
|
||||||
return &DocumentConfiguration{
|
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewClosedDocumentConfiguration(t *testing.T) {
|
func TestNewClosedDocumentConfiguration(t *testing.T) {
|
||||||
cfg := NewClosedDocumentConfiguration()
|
cfg := NewDocumentConfiguration()
|
||||||
assert.False(t, cfg.AllowRemoteReferences)
|
assert.NotNil(t, cfg)
|
||||||
assert.False(t, cfg.AllowFileReferences)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewOpenDocumentConfiguration(t *testing.T) {
|
|
||||||
cfg := NewOpenDocumentConfiguration()
|
|
||||||
assert.True(t, cfg.AllowRemoteReferences)
|
|
||||||
assert.True(t, cfg.AllowFileReferences)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
@@ -70,7 +71,7 @@ email: buckaroo@pb33f.io
|
|||||||
// build low
|
// build low
|
||||||
var lowContact lowbase.Contact
|
var lowContact lowbase.Contact
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowContact)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowContact)
|
||||||
_ = lowContact.Build(nil, cNode.Content[0], nil)
|
_ = lowContact.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
// build high
|
// build high
|
||||||
highContact := NewContact(&lowContact)
|
highContact := NewContact(&lowContact)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -116,7 +117,7 @@ func TestDynamicValue_MarshalYAMLInline(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
||||||
|
|
||||||
lowProxy := new(lowbase.SchemaProxy)
|
lowProxy := new(lowbase.SchemaProxy)
|
||||||
err := lowProxy.Build(nil, node.Content[0], idx)
|
err := lowProxy.Build(context.Background(), nil, node.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -160,7 +161,7 @@ func TestDynamicValue_MarshalYAMLInline_Error(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
||||||
|
|
||||||
lowProxy := new(lowbase.SchemaProxy)
|
lowProxy := new(lowbase.SchemaProxy)
|
||||||
err := lowProxy.Build(nil, node.Content[0], idx)
|
err := lowProxy.Build(context.Background(), nil, node.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -31,7 +32,7 @@ x-hack: code`
|
|||||||
var lowExample lowbase.Example
|
var lowExample lowbase.Example
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowExample)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowExample)
|
||||||
|
|
||||||
_ = lowExample.Build(&cNode, cNode.Content[0], nil)
|
_ = lowExample.Build(context.Background(), &cNode, cNode.Content[0], nil)
|
||||||
|
|
||||||
// build high
|
// build high
|
||||||
highExample := NewExample(&lowExample)
|
highExample := NewExample(&lowExample)
|
||||||
@@ -61,7 +62,7 @@ func TestExtractExamples(t *testing.T) {
|
|||||||
var lowExample lowbase.Example
|
var lowExample lowbase.Example
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowExample)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowExample)
|
||||||
|
|
||||||
_ = lowExample.Build(nil, cNode.Content[0], nil)
|
_ = lowExample.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
examplesMap := orderedmap.New[lowmodel.KeyReference[string], lowmodel.ValueReference[*lowbase.Example]]()
|
examplesMap := orderedmap.New[lowmodel.KeyReference[string], lowmodel.ValueReference[*lowbase.Example]]()
|
||||||
examplesMap.Set(
|
examplesMap.Set(
|
||||||
@@ -90,7 +91,7 @@ x-hack: code`
|
|||||||
_ = lowmodel.BuildModel(node.Content[0], &lowExample)
|
_ = lowmodel.BuildModel(node.Content[0], &lowExample)
|
||||||
|
|
||||||
// build out low-level example
|
// build out low-level example
|
||||||
_ = lowExample.Build(nil, node.Content[0], nil)
|
_ = lowExample.Build(context.Background(), nil, node.Content[0], nil)
|
||||||
|
|
||||||
// create a new high-level example
|
// create a new high-level example
|
||||||
highExample := NewExample(&lowExample)
|
highExample := NewExample(&lowExample)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
@@ -26,7 +27,7 @@ x-hack: code`
|
|||||||
var lowExt lowbase.ExternalDoc
|
var lowExt lowbase.ExternalDoc
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowExt)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowExt)
|
||||||
|
|
||||||
_ = lowExt.Build(nil, cNode.Content[0], nil)
|
_ = lowExt.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
highExt := NewExternalDoc(&lowExt)
|
highExt := NewExternalDoc(&lowExt)
|
||||||
|
|
||||||
@@ -61,7 +62,7 @@ x-hack: code`
|
|||||||
_ = lowmodel.BuildModel(node.Content[0], &lowExt)
|
_ = lowmodel.BuildModel(node.Content[0], &lowExt)
|
||||||
|
|
||||||
// build out low-level properties (like extensions)
|
// build out low-level properties (like extensions)
|
||||||
_ = lowExt.Build(nil, node.Content[0], nil)
|
_ = lowExt.Build(context.Background(), nil, node.Content[0], nil)
|
||||||
|
|
||||||
// create new high-level ExternalDoc
|
// create new high-level ExternalDoc
|
||||||
highExt := NewExternalDoc(&lowExt)
|
highExt := NewExternalDoc(&lowExt)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -32,7 +33,7 @@ x-cli-name: chicken cli`
|
|||||||
|
|
||||||
var lowInfo lowbase.Info
|
var lowInfo lowbase.Info
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowInfo)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowInfo)
|
||||||
_ = lowInfo.Build(nil, cNode.Content[0], nil)
|
_ = lowInfo.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
highInfo := NewInfo(&lowInfo)
|
highInfo := NewInfo(&lowInfo)
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ version: 1.2.3`
|
|||||||
// build out the low-level model
|
// build out the low-level model
|
||||||
var lowInfo lowbase.Info
|
var lowInfo lowbase.Info
|
||||||
_ = lowmodel.BuildModel(&node, &lowInfo)
|
_ = lowmodel.BuildModel(&node, &lowInfo)
|
||||||
_ = lowInfo.Build(nil, node.Content[0], nil)
|
_ = lowInfo.Build(context.Background(), nil, node.Content[0], nil)
|
||||||
|
|
||||||
// build the high level model
|
// build the high level model
|
||||||
highInfo := NewInfo(&lowInfo)
|
highInfo := NewInfo(&lowInfo)
|
||||||
@@ -97,7 +98,7 @@ url: https://opensource.org/licenses/MIT`
|
|||||||
// build out the low-level model
|
// build out the low-level model
|
||||||
var lowLicense lowbase.License
|
var lowLicense lowbase.License
|
||||||
_ = lowmodel.BuildModel(node.Content[0], &lowLicense)
|
_ = lowmodel.BuildModel(node.Content[0], &lowLicense)
|
||||||
_ = lowLicense.Build(nil, node.Content[0], nil)
|
_ = lowLicense.Build(context.Background(), nil, node.Content[0], nil)
|
||||||
|
|
||||||
// build the high level model
|
// build the high level model
|
||||||
highLicense := NewLicense(&lowLicense)
|
highLicense := NewLicense(&lowLicense)
|
||||||
@@ -140,7 +141,7 @@ func TestInfo_Render(t *testing.T) {
|
|||||||
// build low
|
// build low
|
||||||
var lowInfo lowbase.Info
|
var lowInfo lowbase.Info
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowInfo)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowInfo)
|
||||||
_ = lowInfo.Build(nil, cNode.Content[0], nil)
|
_ = lowInfo.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
// build high
|
// build high
|
||||||
highInfo := NewInfo(&lowInfo)
|
highInfo := NewInfo(&lowInfo)
|
||||||
@@ -181,7 +182,7 @@ x-cake:
|
|||||||
// build low
|
// build low
|
||||||
var lowInfo lowbase.Info
|
var lowInfo lowbase.Info
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowInfo)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowInfo)
|
||||||
_ = lowInfo.Build(nil, cNode.Content[0], nil)
|
_ = lowInfo.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
// build high
|
// build high
|
||||||
highInfo := NewInfo(&lowInfo)
|
highInfo := NewInfo(&lowInfo)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -44,7 +45,7 @@ url: https://pb33f.io/not-real
|
|||||||
// build low
|
// build low
|
||||||
var lowLicense lowbase.License
|
var lowLicense lowbase.License
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowLicense)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowLicense)
|
||||||
_ = lowLicense.Build(nil, cNode.Content[0], nil)
|
_ = lowLicense.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
// build high
|
// build high
|
||||||
highLicense := NewLicense(&lowLicense)
|
highLicense := NewLicense(&lowLicense)
|
||||||
@@ -92,7 +93,7 @@ func TestLicense_Render_IdentifierAndURL_Error(t *testing.T) {
|
|||||||
// build low
|
// build low
|
||||||
var lowLicense lowbase.License
|
var lowLicense lowbase.License
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowLicense)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowLicense)
|
||||||
err := lowLicense.Build(nil, cNode.Content[0], nil)
|
err := lowLicense.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -64,12 +64,12 @@ type Schema struct {
|
|||||||
|
|
||||||
// in 3.1 UnevaluatedProperties can be a Schema or a boolean
|
// in 3.1 UnevaluatedProperties can be a Schema or a boolean
|
||||||
// https://github.com/pb33f/libopenapi/issues/118
|
// https://github.com/pb33f/libopenapi/issues/118
|
||||||
UnevaluatedProperties *DynamicValue[*SchemaProxy, *bool] `json:"unevaluatedProperties,omitempty" yaml:"unevaluatedProperties,omitempty"`
|
UnevaluatedProperties *DynamicValue[*SchemaProxy, bool] `json:"unevaluatedProperties,omitempty" yaml:"unevaluatedProperties,omitempty"`
|
||||||
|
|
||||||
// in 3.1 Items can be a Schema or a boolean
|
// in 3.1 Items can be a Schema or a boolean
|
||||||
Items *DynamicValue[*SchemaProxy, bool] `json:"items,omitempty" yaml:"items,omitempty"`
|
Items *DynamicValue[*SchemaProxy, bool] `json:"items,omitempty" yaml:"items,omitempty"`
|
||||||
|
|
||||||
// 3.1 only, part of the JSON Schema spec provides a way to identify a subschema
|
// 3.1 only, part of the JSON Schema spec provides a way to identify a sub-schema
|
||||||
Anchor string `json:"$anchor,omitempty" yaml:"$anchor,omitempty"`
|
Anchor string `json:"$anchor,omitempty" yaml:"$anchor,omitempty"`
|
||||||
|
|
||||||
// Compatible with all versions
|
// Compatible with all versions
|
||||||
@@ -77,8 +77,8 @@ type Schema struct {
|
|||||||
Properties orderedmap.Map[string, *SchemaProxy] `json:"properties,omitempty" yaml:"properties,omitempty"`
|
Properties orderedmap.Map[string, *SchemaProxy] `json:"properties,omitempty" yaml:"properties,omitempty"`
|
||||||
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
Title string `json:"title,omitempty" yaml:"title,omitempty"`
|
||||||
MultipleOf *float64 `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
|
MultipleOf *float64 `json:"multipleOf,omitempty" yaml:"multipleOf,omitempty"`
|
||||||
Maximum *float64 `json:"maximum,omitempty" yaml:"maximum,omitempty"`
|
Maximum *float64 `json:"maximum,renderZero,omitempty" yaml:"maximum,renderZero,omitempty"`
|
||||||
Minimum *float64 `json:"minimum,omitempty" yaml:"minimum,omitempty"`
|
Minimum *float64 `json:"minimum,renderZero,omitempty," yaml:"minimum,renderZero,omitempty"`
|
||||||
MaxLength *int64 `json:"maxLength,omitempty" yaml:"maxLength,omitempty"`
|
MaxLength *int64 `json:"maxLength,omitempty" yaml:"maxLength,omitempty"`
|
||||||
MinLength *int64 `json:"minLength,omitempty" yaml:"minLength,omitempty"`
|
MinLength *int64 `json:"minLength,omitempty" yaml:"minLength,omitempty"`
|
||||||
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
|
Pattern string `json:"pattern,omitempty" yaml:"pattern,omitempty"`
|
||||||
@@ -90,7 +90,7 @@ type Schema struct {
|
|||||||
MinProperties *int64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
|
MinProperties *int64 `json:"minProperties,omitempty" yaml:"minProperties,omitempty"`
|
||||||
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
Required []string `json:"required,omitempty" yaml:"required,omitempty"`
|
||||||
Enum []any `json:"enum,omitempty" yaml:"enum,omitempty"`
|
Enum []any `json:"enum,omitempty" yaml:"enum,omitempty"`
|
||||||
AdditionalProperties any `json:"additionalProperties,omitempty" yaml:"additionalProperties,renderZero,omitempty"`
|
AdditionalProperties *DynamicValue[*SchemaProxy, bool] `json:"additionalProperties,renderZero,omitempty" yaml:"additionalProperties,renderZero,omitempty"`
|
||||||
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
Description string `json:"description,omitempty" yaml:"description,omitempty"`
|
||||||
Default any `json:"default,omitempty" yaml:"default,renderZero,omitempty"`
|
Default any `json:"default,omitempty" yaml:"default,renderZero,omitempty"`
|
||||||
Const any `json:"const,omitempty" yaml:"const,renderZero,omitempty"`
|
Const any `json:"const,omitempty" yaml:"const,renderZero,omitempty"`
|
||||||
@@ -212,29 +212,22 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
Value: schema.UnevaluatedItems.Value,
|
Value: schema.UnevaluatedItems.Value,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// check if unevaluated properties is a schema
|
|
||||||
if !schema.UnevaluatedProperties.IsEmpty() && schema.UnevaluatedProperties.Value.IsA() {
|
var unevaluatedProperties *DynamicValue[*SchemaProxy, bool]
|
||||||
s.UnevaluatedProperties = &DynamicValue[*SchemaProxy, *bool]{
|
if !schema.UnevaluatedProperties.IsEmpty() {
|
||||||
A: NewSchemaProxy(
|
if schema.UnevaluatedProperties.Value.IsA() {
|
||||||
&lowmodel.NodeReference[*base.SchemaProxy]{
|
unevaluatedProperties = &DynamicValue[*SchemaProxy, bool]{
|
||||||
|
A: NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||||
ValueNode: schema.UnevaluatedProperties.ValueNode,
|
ValueNode: schema.UnevaluatedProperties.ValueNode,
|
||||||
Value: schema.UnevaluatedProperties.Value.A,
|
Value: schema.UnevaluatedProperties.Value.A,
|
||||||
},
|
KeyNode: schema.UnevaluatedProperties.KeyNode,
|
||||||
),
|
}),
|
||||||
N: 0,
|
}
|
||||||
|
} else {
|
||||||
|
unevaluatedProperties = &DynamicValue[*SchemaProxy, bool]{N: 1, B: schema.UnevaluatedProperties.Value.B}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.UnevaluatedProperties = unevaluatedProperties
|
||||||
// check if unevaluated properties is a bool
|
|
||||||
if !schema.UnevaluatedProperties.IsEmpty() && schema.UnevaluatedProperties.Value.IsB() {
|
|
||||||
s.UnevaluatedProperties = &DynamicValue[*SchemaProxy, *bool]{
|
|
||||||
B: schema.UnevaluatedProperties.Value.B,
|
|
||||||
N: 1,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !schema.UnevaluatedProperties.IsEmpty() {
|
|
||||||
}
|
|
||||||
|
|
||||||
s.Pattern = schema.Pattern.Value
|
s.Pattern = schema.Pattern.Value
|
||||||
s.Format = schema.Format.Value
|
s.Format = schema.Format.Value
|
||||||
@@ -249,19 +242,23 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
s.Type = append(s.Type, schema.Type.Value.B[i].Value)
|
s.Type = append(s.Type, schema.Type.Value.B[i].Value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if schema.AdditionalProperties.Value != nil {
|
|
||||||
if addPropSchema, ok := schema.AdditionalProperties.Value.(*base.SchemaProxy); ok {
|
|
||||||
s.AdditionalProperties = NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
|
||||||
KeyNode: schema.AdditionalProperties.KeyNode,
|
|
||||||
ValueNode: schema.AdditionalProperties.ValueNode,
|
|
||||||
Value: addPropSchema,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// TODO: check for slice and map types and unpack correctly.
|
|
||||||
|
|
||||||
s.AdditionalProperties = schema.AdditionalProperties.Value
|
var additionalProperties *DynamicValue[*SchemaProxy, bool]
|
||||||
|
if !schema.AdditionalProperties.IsEmpty() {
|
||||||
|
if schema.AdditionalProperties.Value.IsA() {
|
||||||
|
additionalProperties = &DynamicValue[*SchemaProxy, bool]{
|
||||||
|
A: NewSchemaProxy(&lowmodel.NodeReference[*base.SchemaProxy]{
|
||||||
|
ValueNode: schema.AdditionalProperties.ValueNode,
|
||||||
|
Value: schema.AdditionalProperties.Value.A,
|
||||||
|
KeyNode: schema.AdditionalProperties.KeyNode,
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
additionalProperties = &DynamicValue[*SchemaProxy, bool]{N: 1, B: schema.AdditionalProperties.Value.B}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
s.AdditionalProperties = additionalProperties
|
||||||
|
|
||||||
s.Description = schema.Description.Value
|
s.Description = schema.Description.Value
|
||||||
s.Default = schema.Default.Value
|
s.Default = schema.Default.Value
|
||||||
s.Const = schema.Const.Value
|
s.Const = schema.Const.Value
|
||||||
@@ -306,7 +303,6 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
s.Anchor = schema.Anchor.Value
|
s.Anchor = schema.Anchor.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: check this behavior.
|
|
||||||
for i := range schema.Enum.Value {
|
for i := range schema.Enum.Value {
|
||||||
enum = append(enum, schema.Enum.Value[i].Value)
|
enum = append(enum, schema.Enum.Value[i].Value)
|
||||||
}
|
}
|
||||||
@@ -423,7 +419,8 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
Value: schema.Items.Value.A,
|
Value: schema.Items.Value.A,
|
||||||
KeyNode: schema.Items.KeyNode,
|
KeyNode: schema.Items.KeyNode,
|
||||||
},
|
},
|
||||||
)}
|
),
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
items = &DynamicValue[*SchemaProxy, bool]{N: 1, B: schema.Items.Value.B}
|
items = &DynamicValue[*SchemaProxy, bool]{N: 1, B: schema.Items.Value.B}
|
||||||
}
|
}
|
||||||
@@ -437,7 +434,7 @@ func NewSchema(schema *base.Schema) *Schema {
|
|||||||
completeChildren := 0
|
completeChildren := 0
|
||||||
if children > 0 {
|
if children > 0 {
|
||||||
allDone:
|
allDone:
|
||||||
for true {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-polyCompletedChan:
|
case <-polyCompletedChan:
|
||||||
completeChildren++
|
completeChildren++
|
||||||
@@ -471,8 +468,8 @@ func (s *Schema) Render() ([]byte, error) {
|
|||||||
return yaml.Marshal(s)
|
return yaml.Marshal(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
// RenderInline will return a YAML representation of the Schema object as a byte slice. All of the
|
// RenderInline will return a YAML representation of the Schema object as a byte slice.
|
||||||
// $ref values will be inlined, as in resolved in place.
|
// All the $ref values will be inlined, as in resolved in place.
|
||||||
//
|
//
|
||||||
// Make sure you don't have any circular references!
|
// Make sure you don't have any circular references!
|
||||||
func (s *Schema) RenderInline() ([]byte, error) {
|
func (s *Schema) RenderInline() ([]byte, error) {
|
||||||
@@ -483,11 +480,26 @@ func (s *Schema) RenderInline() ([]byte, error) {
|
|||||||
// MarshalYAML will create a ready to render YAML representation of the ExternalDoc object.
|
// MarshalYAML will create a ready to render YAML representation of the ExternalDoc object.
|
||||||
func (s *Schema) MarshalYAML() (interface{}, error) {
|
func (s *Schema) MarshalYAML() (interface{}, error) {
|
||||||
nb := high.NewNodeBuilder(s, s.low)
|
nb := high.NewNodeBuilder(s, s.low)
|
||||||
|
|
||||||
|
// determine index version
|
||||||
|
idx := s.GoLow().Index
|
||||||
|
if idx != nil {
|
||||||
|
if idx.GetConfig().SpecInfo != nil {
|
||||||
|
nb.Version = idx.GetConfig().SpecInfo.VersionNumeric
|
||||||
|
}
|
||||||
|
}
|
||||||
return nb.Render(), nil
|
return nb.Render(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Schema) MarshalYAMLInline() (interface{}, error) {
|
func (s *Schema) MarshalYAMLInline() (interface{}, error) {
|
||||||
nb := high.NewNodeBuilder(s, s.low)
|
nb := high.NewNodeBuilder(s, s.low)
|
||||||
nb.Resolve = true
|
nb.Resolve = true
|
||||||
|
// determine index version
|
||||||
|
idx := s.GoLow().Index
|
||||||
|
if idx != nil {
|
||||||
|
if idx.GetConfig().SpecInfo != nil {
|
||||||
|
nb.Version = idx.GetConfig().SpecInfo.VersionNumeric
|
||||||
|
}
|
||||||
|
}
|
||||||
return nb.Render(), nil
|
return nb.Render(), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -114,6 +115,15 @@ func (sp *SchemaProxy) GetReference() string {
|
|||||||
return sp.schema.Value.GetSchemaReference()
|
return sp.schema.Value.GetSchemaReference()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetReferenceOrigin returns a pointer to the index.NodeOrigin of the $ref if this SchemaProxy is a reference to another Schema.
|
||||||
|
// returns nil if the origin cannot be found (which, means there is a bug, and we need to fix it).
|
||||||
|
func (sp *SchemaProxy) GetReferenceOrigin() *index.NodeOrigin {
|
||||||
|
if sp.schema != nil {
|
||||||
|
return sp.schema.Value.GetSchemaReferenceLocation()
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// BuildSchema operates the same way as Schema, except it will return any error along with the *Schema
|
// BuildSchema operates the same way as Schema, except it will return any error along with the *Schema
|
||||||
func (sp *SchemaProxy) BuildSchema() (*Schema, error) {
|
func (sp *SchemaProxy) BuildSchema() (*Schema, error) {
|
||||||
if sp.rendered != nil {
|
if sp.rendered != nil {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -40,7 +41,7 @@ func TestSchemaProxy_MarshalYAML(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
||||||
|
|
||||||
lowProxy := new(lowbase.SchemaProxy)
|
lowProxy := new(lowbase.SchemaProxy)
|
||||||
err := lowProxy.Build(nil, node.Content[0], idx)
|
err := lowProxy.Build(context.Background(), nil, node.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -49,6 +50,9 @@ func TestSchemaProxy_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
sp := NewSchemaProxy(&lowRef)
|
sp := NewSchemaProxy(&lowRef)
|
||||||
|
|
||||||
|
origin := sp.GetReferenceOrigin()
|
||||||
|
assert.Nil(t, origin)
|
||||||
|
|
||||||
rend, _ := sp.Render()
|
rend, _ := sp.Render()
|
||||||
assert.Equal(t, "$ref: '#/components/schemas/nice'", strings.TrimSpace(string(rend)))
|
assert.Equal(t, "$ref: '#/components/schemas/nice'", strings.TrimSpace(string(rend)))
|
||||||
|
|
||||||
@@ -65,3 +69,8 @@ func TestCreateSchemaProxyRef(t *testing.T) {
|
|||||||
assert.Equal(t, "#/components/schemas/MySchema", sp.GetReference())
|
assert.Equal(t, "#/components/schemas/MySchema", sp.GetReference())
|
||||||
assert.True(t, sp.IsReference())
|
assert.True(t, sp.IsReference())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSchemaProxy_NoSchema_GetOrigin(t *testing.T) {
|
||||||
|
sp := &SchemaProxy{}
|
||||||
|
assert.Nil(t, sp.GetReferenceOrigin())
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,10 +4,13 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -49,7 +52,7 @@ func TestNewSchemaProxy(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(yml), &compNode)
|
_ = yaml.Unmarshal([]byte(yml), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], idx)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -90,7 +93,7 @@ func TestNewSchemaProxyRender(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(yml), &compNode)
|
_ = yaml.Unmarshal([]byte(yml), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], idx)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -111,7 +114,6 @@ func TestNewSchemaProxyRender(t *testing.T) {
|
|||||||
rice:
|
rice:
|
||||||
$ref: '#/components/schemas/rice'`
|
$ref: '#/components/schemas/rice'`
|
||||||
assert.Equal(t, desired, strings.TrimSpace(string(rend)))
|
assert.Equal(t, desired, strings.TrimSpace(string(rend)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewSchemaProxy_WithObject(t *testing.T) {
|
func TestNewSchemaProxy_WithObject(t *testing.T) {
|
||||||
@@ -217,10 +219,7 @@ properties:
|
|||||||
type: number
|
type: number
|
||||||
description: a number
|
description: a number
|
||||||
example: "2"
|
example: "2"
|
||||||
additionalProperties:
|
additionalProperties: false
|
||||||
- chicken
|
|
||||||
- nugget
|
|
||||||
- soup
|
|
||||||
somethingB:
|
somethingB:
|
||||||
type: object
|
type: object
|
||||||
exclusiveMinimum: true
|
exclusiveMinimum: true
|
||||||
@@ -241,8 +240,7 @@ properties:
|
|||||||
attribute: true
|
attribute: true
|
||||||
x-pizza: love
|
x-pizza: love
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
why: yes
|
type: string
|
||||||
thatIs: true
|
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
required:
|
required:
|
||||||
- them
|
- them
|
||||||
@@ -274,7 +272,7 @@ $anchor: anchor`
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -315,12 +313,12 @@ $anchor: anchor`
|
|||||||
assert.Equal(t, "anchor", compiled.Anchor)
|
assert.Equal(t, "anchor", compiled.Anchor)
|
||||||
|
|
||||||
wentLow := compiled.GoLow()
|
wentLow := compiled.GoLow()
|
||||||
assert.Equal(t, 129, wentLow.AdditionalProperties.ValueNode.Line)
|
assert.Equal(t, 125, wentLow.AdditionalProperties.ValueNode.Line)
|
||||||
assert.NotNil(t, compiled.GoLowUntyped())
|
assert.NotNil(t, compiled.GoLowUntyped())
|
||||||
|
|
||||||
// now render it out!
|
// now render it out!
|
||||||
schemaBytes, _ := compiled.Render()
|
schemaBytes, _ := compiled.Render()
|
||||||
assert.Len(t, schemaBytes, 3494)
|
assert.Len(t, schemaBytes, 3417)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSchemaObjectWithAllOfSequenceOrder(t *testing.T) {
|
func TestSchemaObjectWithAllOfSequenceOrder(t *testing.T) {
|
||||||
@@ -348,7 +346,7 @@ func TestSchemaObjectWithAllOfSequenceOrder(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -485,7 +483,7 @@ required: [cake, fish]`
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -504,7 +502,7 @@ required: [cake, fish]`
|
|||||||
assert.Equal(t, float64(334), compiled.Properties.GetOrZero("somethingB").Schema().ExclusiveMaximum.B)
|
assert.Equal(t, float64(334), compiled.Properties.GetOrZero("somethingB").Schema().ExclusiveMaximum.B)
|
||||||
assert.Len(t, compiled.Properties.GetOrZero("somethingB").Schema().Properties.GetOrZero("somethingBProp").Schema().Type, 2)
|
assert.Len(t, compiled.Properties.GetOrZero("somethingB").Schema().Properties.GetOrZero("somethingBProp").Schema().Type, 2)
|
||||||
|
|
||||||
assert.Equal(t, "nice", compiled.AdditionalProperties.(*SchemaProxy).Schema().Description)
|
assert.Equal(t, "nice", compiled.AdditionalProperties.A.Schema().Description)
|
||||||
|
|
||||||
wentLow := compiled.GoLow()
|
wentLow := compiled.GoLow()
|
||||||
assert.Equal(t, 97, wentLow.AdditionalProperties.ValueNode.Line)
|
assert.Equal(t, 97, wentLow.AdditionalProperties.ValueNode.Line)
|
||||||
@@ -541,7 +539,7 @@ func TestSchemaProxy_GoLow(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
_ = yaml.Unmarshal([]byte(ymlSchema), &node)
|
||||||
|
|
||||||
lowProxy := new(lowbase.SchemaProxy)
|
lowProxy := new(lowbase.SchemaProxy)
|
||||||
err := lowProxy.Build(nil, node.Content[0], idx)
|
err := lowProxy.Build(context.Background(), nil, node.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
lowRef := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -556,7 +554,6 @@ func TestSchemaProxy_GoLow(t *testing.T) {
|
|||||||
spNil := NewSchemaProxy(nil)
|
spNil := NewSchemaProxy(nil)
|
||||||
assert.Nil(t, spNil.GoLow())
|
assert.Nil(t, spNil.GoLow())
|
||||||
assert.Nil(t, spNil.GoLowUntyped())
|
assert.Nil(t, spNil.GoLowUntyped())
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func getHighSchema(t *testing.T, yml string) *Schema {
|
func getHighSchema(t *testing.T, yml string) *Schema {
|
||||||
@@ -567,7 +564,7 @@ func getHighSchema(t *testing.T, yml string) *Schema {
|
|||||||
// build out the low-level model
|
// build out the low-level model
|
||||||
var lowSchema lowbase.Schema
|
var lowSchema lowbase.Schema
|
||||||
assert.NoError(t, low.BuildModel(node.Content[0], &lowSchema))
|
assert.NoError(t, low.BuildModel(node.Content[0], &lowSchema))
|
||||||
assert.NoError(t, lowSchema.Build(node.Content[0], nil))
|
assert.NoError(t, lowSchema.Build(context.Background(), node.Content[0], nil))
|
||||||
|
|
||||||
// build the high level model
|
// build the high level model
|
||||||
return NewSchema(&lowSchema)
|
return NewSchema(&lowSchema)
|
||||||
@@ -728,7 +725,7 @@ properties:
|
|||||||
// build out the low-level model
|
// build out the low-level model
|
||||||
var lowSchema lowbase.Schema
|
var lowSchema lowbase.Schema
|
||||||
_ = low.BuildModel(node.Content[0], &lowSchema)
|
_ = low.BuildModel(node.Content[0], &lowSchema)
|
||||||
_ = lowSchema.Build(node.Content[0], nil)
|
_ = lowSchema.Build(context.Background(), node.Content[0], nil)
|
||||||
|
|
||||||
// build the high level model
|
// build the high level model
|
||||||
highSchema := NewSchema(&lowSchema)
|
highSchema := NewSchema(&lowSchema)
|
||||||
@@ -757,7 +754,7 @@ properties:
|
|||||||
// build out the low-level model
|
// build out the low-level model
|
||||||
var lowSchema lowbase.SchemaProxy
|
var lowSchema lowbase.SchemaProxy
|
||||||
_ = low.BuildModel(node.Content[0], &lowSchema)
|
_ = low.BuildModel(node.Content[0], &lowSchema)
|
||||||
_ = lowSchema.Build(nil, node.Content[0], nil)
|
_ = lowSchema.Build(context.Background(), nil, node.Content[0], nil)
|
||||||
|
|
||||||
// build the high level schema proxy
|
// build the high level schema proxy
|
||||||
highSchema := NewSchemaProxy(&low.NodeReference[*lowbase.SchemaProxy]{
|
highSchema := NewSchemaProxy(&low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -817,7 +814,7 @@ allOf:
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -836,7 +833,6 @@ allOf:
|
|||||||
// now render it out, it should be identical.
|
// now render it out, it should be identical.
|
||||||
schemaBytes, _ := compiled.Render()
|
schemaBytes, _ := compiled.Render()
|
||||||
assert.Equal(t, testSpec, string(schemaBytes))
|
assert.Equal(t, testSpec, string(schemaBytes))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewSchemaProxy_RenderSchemaWithMultipleObjectTypes(t *testing.T) {
|
func TestNewSchemaProxy_RenderSchemaWithMultipleObjectTypes(t *testing.T) {
|
||||||
@@ -881,7 +877,7 @@ items:
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -934,8 +930,7 @@ func TestNewSchemaProxy_RenderSchemaEnsurePropertyOrdering(t *testing.T) {
|
|||||||
attribute: true
|
attribute: true
|
||||||
x-pizza: love
|
x-pizza: love
|
||||||
additionalProperties:
|
additionalProperties:
|
||||||
why: yes
|
type: string
|
||||||
thatIs: true
|
|
||||||
additionalProperties: true
|
additionalProperties: true
|
||||||
xml:
|
xml:
|
||||||
name: XML Thing`
|
name: XML Thing`
|
||||||
@@ -944,7 +939,7 @@ xml:
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -973,7 +968,7 @@ func TestNewSchemaProxy_RenderSchemaCheckDiscriminatorMappingOrder(t *testing.T)
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -989,60 +984,6 @@ func TestNewSchemaProxy_RenderSchemaCheckDiscriminatorMappingOrder(t *testing.T)
|
|||||||
assert.Equal(t, testSpec, strings.TrimSpace(string(schemaBytes)))
|
assert.Equal(t, testSpec, strings.TrimSpace(string(schemaBytes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestNewSchemaProxy_RenderSchemaCheckAdditionalPropertiesSlice(t *testing.T) {
|
|
||||||
testSpec := `additionalProperties:
|
|
||||||
- one
|
|
||||||
- two
|
|
||||||
- miss a few
|
|
||||||
- ninety nine
|
|
||||||
- hundred`
|
|
||||||
|
|
||||||
var compNode yaml.Node
|
|
||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
|
||||||
Value: sp,
|
|
||||||
ValueNode: compNode.Content[0],
|
|
||||||
}
|
|
||||||
|
|
||||||
schemaProxy := NewSchemaProxy(&lowproxy)
|
|
||||||
compiled := schemaProxy.Schema()
|
|
||||||
|
|
||||||
// now render it out, it should be identical.
|
|
||||||
schemaBytes, _ := compiled.Render()
|
|
||||||
assert.Len(t, schemaBytes, 91)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewSchemaProxy_RenderSchemaCheckAdditionalPropertiesSliceMap(t *testing.T) {
|
|
||||||
testSpec := `additionalProperties:
|
|
||||||
- nice: cake
|
|
||||||
- yummy: beer
|
|
||||||
- hot: coffee`
|
|
||||||
|
|
||||||
var compNode yaml.Node
|
|
||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
|
||||||
assert.NoError(t, err)
|
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
|
||||||
Value: sp,
|
|
||||||
ValueNode: compNode.Content[0],
|
|
||||||
}
|
|
||||||
|
|
||||||
schemaProxy := NewSchemaProxy(&lowproxy)
|
|
||||||
compiled := schemaProxy.Schema()
|
|
||||||
|
|
||||||
// now render it out, it should be identical.
|
|
||||||
schemaBytes, _ := compiled.Render()
|
|
||||||
assert.Len(t, schemaBytes, 75)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestNewSchemaProxy_CheckDefaultBooleanFalse(t *testing.T) {
|
func TestNewSchemaProxy_CheckDefaultBooleanFalse(t *testing.T) {
|
||||||
testSpec := `default: false`
|
testSpec := `default: false`
|
||||||
|
|
||||||
@@ -1050,7 +991,7 @@ func TestNewSchemaProxy_CheckDefaultBooleanFalse(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -1073,7 +1014,7 @@ func TestNewSchemaProxy_RenderAdditionalPropertiesFalse(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
err := sp.Build(nil, compNode.Content[0], nil)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -1117,7 +1058,7 @@ components:
|
|||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
|
||||||
err := sp.Build(nil, compNode.Content[0], idx)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -1169,7 +1110,7 @@ components:
|
|||||||
|
|
||||||
sp := new(lowbase.SchemaProxy)
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
|
||||||
err := sp.Build(nil, compNode.Content[0], idx)
|
err := sp.Build(context.Background(), nil, compNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
@@ -1192,8 +1133,7 @@ unevaluatedProperties: true
|
|||||||
`
|
`
|
||||||
highSchema := getHighSchema(t, yml)
|
highSchema := getHighSchema(t, yml)
|
||||||
|
|
||||||
value := true
|
assert.True(t, highSchema.UnevaluatedProperties.B)
|
||||||
assert.EqualValues(t, &value, highSchema.UnevaluatedProperties.B)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnevaluatedPropertiesBoolean_False(t *testing.T) {
|
func TestUnevaluatedPropertiesBoolean_False(t *testing.T) {
|
||||||
@@ -1203,6 +1143,147 @@ unevaluatedProperties: false
|
|||||||
`
|
`
|
||||||
highSchema := getHighSchema(t, yml)
|
highSchema := getHighSchema(t, yml)
|
||||||
|
|
||||||
value := false
|
assert.False(t, highSchema.UnevaluatedProperties.B)
|
||||||
assert.EqualValues(t, &value, highSchema.UnevaluatedProperties.B)
|
}
|
||||||
|
|
||||||
|
func TestUnevaluatedPropertiesBoolean_Unset(t *testing.T) {
|
||||||
|
yml := `
|
||||||
|
type: number
|
||||||
|
`
|
||||||
|
highSchema := getHighSchema(t, yml)
|
||||||
|
|
||||||
|
assert.Nil(t, highSchema.UnevaluatedProperties)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAdditionalProperties(t *testing.T) {
|
||||||
|
testSpec := `type: object
|
||||||
|
properties:
|
||||||
|
additionalPropertiesSimpleSchema:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
type: string
|
||||||
|
additionalPropertiesBool:
|
||||||
|
type: object
|
||||||
|
additionalProperties: true
|
||||||
|
additionalPropertiesAnyOf:
|
||||||
|
type: object
|
||||||
|
additionalProperties:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
`
|
||||||
|
|
||||||
|
var compNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
Value: sp,
|
||||||
|
ValueNode: compNode.Content[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaProxy := NewSchemaProxy(&lowproxy)
|
||||||
|
compiled := schemaProxy.Schema()
|
||||||
|
|
||||||
|
assert.Equal(t, []string{"string"}, compiled.Properties.GetOrZero("additionalPropertiesSimpleSchema").Schema().AdditionalProperties.A.Schema().Type)
|
||||||
|
assert.Equal(t, true, compiled.Properties.GetOrZero("additionalPropertiesBool").Schema().AdditionalProperties.B)
|
||||||
|
assert.Equal(t, []string{"string"}, compiled.Properties.GetOrZero("additionalPropertiesAnyOf").Schema().AdditionalProperties.A.Schema().AnyOf[0].Schema().Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_RenderProxyWithConfig_3(t *testing.T) {
|
||||||
|
testSpec := `exclusiveMinimum: true`
|
||||||
|
|
||||||
|
var compNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
err := sp.Build(context.Background(), nil, compNode.Content[0], nil)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.0,
|
||||||
|
}
|
||||||
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
Value: sp,
|
||||||
|
ValueNode: compNode.Content[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaProxy := NewSchemaProxy(&lowproxy)
|
||||||
|
compiled := schemaProxy.Schema()
|
||||||
|
|
||||||
|
// now render it out, it should be identical.
|
||||||
|
schemaBytes, _ := compiled.Render()
|
||||||
|
assert.Equal(t, testSpec, strings.TrimSpace(string(schemaBytes)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_RenderProxyWithConfig_Corrected_31(t *testing.T) {
|
||||||
|
testSpec := `exclusiveMinimum: true`
|
||||||
|
testSpecCorrect := `exclusiveMinimum: 0`
|
||||||
|
|
||||||
|
var compNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.1,
|
||||||
|
}
|
||||||
|
idx := index.NewSpecIndexWithConfig(compNode.Content[0], config)
|
||||||
|
|
||||||
|
err := sp.Build(context.Background(), nil, compNode.Content[0], idx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
Value: sp,
|
||||||
|
ValueNode: compNode.Content[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaProxy := NewSchemaProxy(&lowproxy)
|
||||||
|
compiled := schemaProxy.Schema()
|
||||||
|
|
||||||
|
// now render it out, it should be identical.
|
||||||
|
schemaBytes, _ := compiled.Render()
|
||||||
|
assert.Equal(t, testSpecCorrect, strings.TrimSpace(string(schemaBytes)))
|
||||||
|
|
||||||
|
schemaBytes, _ = compiled.RenderInline()
|
||||||
|
assert.Equal(t, testSpecCorrect, strings.TrimSpace(string(schemaBytes)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_RenderProxyWithConfig_Corrected_3(t *testing.T) {
|
||||||
|
testSpec := `exclusiveMinimum: 0`
|
||||||
|
testSpecCorrect := `exclusiveMinimum: false`
|
||||||
|
|
||||||
|
var compNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(testSpec), &compNode)
|
||||||
|
|
||||||
|
sp := new(lowbase.SchemaProxy)
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.0,
|
||||||
|
}
|
||||||
|
idx := index.NewSpecIndexWithConfig(compNode.Content[0], config)
|
||||||
|
|
||||||
|
err := sp.Build(context.Background(), nil, compNode.Content[0], idx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
lowproxy := low.NodeReference[*lowbase.SchemaProxy]{
|
||||||
|
Value: sp,
|
||||||
|
ValueNode: compNode.Content[0],
|
||||||
|
}
|
||||||
|
|
||||||
|
schemaProxy := NewSchemaProxy(&lowproxy)
|
||||||
|
compiled := schemaProxy.Schema()
|
||||||
|
|
||||||
|
// now render it out, it should be identical.
|
||||||
|
schemaBytes, _ := compiled.Render()
|
||||||
|
assert.Equal(t, testSpecCorrect, strings.TrimSpace(string(schemaBytes)))
|
||||||
|
|
||||||
|
schemaBytes, _ = compiled.RenderInline()
|
||||||
|
assert.Equal(t, testSpecCorrect, strings.TrimSpace(string(schemaBytes)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ cake:
|
|||||||
var lowExt lowbase.SecurityRequirement
|
var lowExt lowbase.SecurityRequirement
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowExt)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowExt)
|
||||||
|
|
||||||
_ = lowExt.Build(nil, cNode.Content[0], nil)
|
_ = lowExt.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
highExt := NewSecurityRequirement(&lowExt)
|
highExt := NewSecurityRequirement(&lowExt)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -28,7 +29,7 @@ x-hack: code`
|
|||||||
|
|
||||||
var lowTag lowbase.Tag
|
var lowTag lowbase.Tag
|
||||||
_ = lowmodel.BuildModel(cNode.Content[0], &lowTag)
|
_ = lowmodel.BuildModel(cNode.Content[0], &lowTag)
|
||||||
_ = lowTag.Build(nil, cNode.Content[0], nil)
|
_ = lowTag.Build(context.Background(), nil, cNode.Content[0], nil)
|
||||||
|
|
||||||
highTag := NewTag(&lowTag)
|
highTag := NewTag(&lowTag)
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ x-hack: code`
|
|||||||
// build out the low-level model
|
// build out the low-level model
|
||||||
var lowTag lowbase.Tag
|
var lowTag lowbase.Tag
|
||||||
_ = lowmodel.BuildModel(node.Content[0], &lowTag)
|
_ = lowmodel.BuildModel(node.Content[0], &lowTag)
|
||||||
_ = lowTag.Build(nil, node.Content[0], nil)
|
_ = lowTag.Build(context.Background(), nil, node.Content[0], nil)
|
||||||
|
|
||||||
// build the high level tag
|
// build the high level tag
|
||||||
highTag := NewTag(&lowTag)
|
highTag := NewTag(&lowTag)
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ type NodeEntry struct {
|
|||||||
// NodeBuilder is a structure used by libopenapi high-level objects, to render themselves back to YAML.
|
// NodeBuilder is a structure used by libopenapi high-level objects, to render themselves back to YAML.
|
||||||
// this allows high-level objects to be 'mutable' because all changes will be rendered out.
|
// this allows high-level objects to be 'mutable' because all changes will be rendered out.
|
||||||
type NodeBuilder struct {
|
type NodeBuilder struct {
|
||||||
|
Version float32
|
||||||
Nodes []*NodeEntry
|
Nodes []*NodeEntry
|
||||||
High any
|
High any
|
||||||
Low any
|
Low any
|
||||||
@@ -587,8 +588,12 @@ func (n *NodeBuilder) AddYAMLNode(parent *yaml.Node, entry *NodeEntry) *yaml.Nod
|
|||||||
}
|
}
|
||||||
if b, bok := value.(*float64); bok {
|
if b, bok := value.(*float64); bok {
|
||||||
encodeSkip = true
|
encodeSkip = true
|
||||||
|
if *b > 0 || (entry.RenderZero && entry.Line > 0) {
|
||||||
if *b > 0 {
|
if *b > 0 {
|
||||||
valueNode = utils.CreateFloatNode(strconv.FormatFloat(*b, 'f', -1, 64))
|
valueNode = utils.CreateFloatNode(strconv.FormatFloat(*b, 'f', -1, 64))
|
||||||
|
} else {
|
||||||
|
valueNode = utils.CreateIntNode(strconv.FormatFloat(*b, 'f', -1, 64))
|
||||||
|
}
|
||||||
valueNode.Line = line
|
valueNode.Line = line
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -642,7 +647,7 @@ func (n *NodeBuilder) extractLowMapKeysWrapped(iu reflect.Value, x string, order
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (n *NodeBuilder) extractLowMapKeys(fg reflect.Value, x string, found bool, orderedCollection []*NodeEntry, m reflect.Value, k reflect.Value) (bool, []*NodeEntry) {
|
func (n *NodeBuilder) extractLowMapKeys(fg reflect.Value, x string, found bool, orderedCollection []*NodeEntry, m reflect.Value, k reflect.Value) (bool, []*NodeEntry) {
|
||||||
if !fg.IsZero() {
|
if fg.IsValid() && !fg.IsZero() {
|
||||||
for j, ky := range fg.MapKeys() {
|
for j, ky := range fg.MapKeys() {
|
||||||
hu := ky.Interface()
|
hu := ky.Interface()
|
||||||
if we, wok := hu.(low.HasKeyNode); wok {
|
if we, wok := hu.(low.HasKeyNode); wok {
|
||||||
|
|||||||
@@ -90,6 +90,7 @@ type test1 struct {
|
|||||||
Thugg *bool `yaml:"thugg,renderZero"`
|
Thugg *bool `yaml:"thugg,renderZero"`
|
||||||
Thurr *int64 `yaml:"thurr,omitempty"`
|
Thurr *int64 `yaml:"thurr,omitempty"`
|
||||||
Thral *float64 `yaml:"thral,omitempty"`
|
Thral *float64 `yaml:"thral,omitempty"`
|
||||||
|
Throo *float64 `yaml:"throo,renderZero,omitempty"`
|
||||||
Tharg []string `yaml:"tharg,omitempty"`
|
Tharg []string `yaml:"tharg,omitempty"`
|
||||||
Type []string `yaml:"type,omitempty"`
|
Type []string `yaml:"type,omitempty"`
|
||||||
Throg []*key `yaml:"throg,omitempty"`
|
Throg []*key `yaml:"throg,omitempty"`
|
||||||
@@ -423,6 +424,7 @@ func TestNewNodeBuilder_MapKeyHasValue(t *testing.T) {
|
|||||||
type test1low struct {
|
type test1low struct {
|
||||||
Thrug key `yaml:"thrug"`
|
Thrug key `yaml:"thrug"`
|
||||||
Thugg *bool `yaml:"thugg"`
|
Thugg *bool `yaml:"thugg"`
|
||||||
|
Throo *float32 `yaml:"throo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 := test1low{
|
t2 := test1low{
|
||||||
@@ -456,6 +458,7 @@ func TestNewNodeBuilder_MapKeyHasValueThatHasValue(t *testing.T) {
|
|||||||
type test1low struct {
|
type test1low struct {
|
||||||
Thomp key `yaml:"thomp"`
|
Thomp key `yaml:"thomp"`
|
||||||
Thugg *bool `yaml:"thugg"`
|
Thugg *bool `yaml:"thugg"`
|
||||||
|
Throo *float32 `yaml:"throo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 := test1low{
|
t2 := test1low{
|
||||||
@@ -495,6 +498,7 @@ func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatch(t *testing.T) {
|
|||||||
type test1low struct {
|
type test1low struct {
|
||||||
Thomp low.NodeReference[map[key]string] `yaml:"thomp"`
|
Thomp low.NodeReference[map[key]string] `yaml:"thomp"`
|
||||||
Thugg *bool `yaml:"thugg"`
|
Thugg *bool `yaml:"thugg"`
|
||||||
|
Throo *float32 `yaml:"throo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
g := low.NodeReference[map[key]string]{
|
g := low.NodeReference[map[key]string]{
|
||||||
@@ -529,6 +533,7 @@ func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatchKeyNode(t *testing.T) {
|
|||||||
type test1low struct {
|
type test1low struct {
|
||||||
Thomp low.NodeReference[map[key]string] `yaml:"thomp"`
|
Thomp low.NodeReference[map[key]string] `yaml:"thomp"`
|
||||||
Thugg *bool `yaml:"thugg"`
|
Thugg *bool `yaml:"thugg"`
|
||||||
|
Throo *float32 `yaml:"throo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
g := low.NodeReference[map[key]string]{
|
g := low.NodeReference[map[key]string]{
|
||||||
@@ -563,6 +568,7 @@ func TestNewNodeBuilder_MapKeyHasValueThatHasValueMatch_NoWrap(t *testing.T) {
|
|||||||
type test1low struct {
|
type test1low struct {
|
||||||
Thomp map[key]string `yaml:"thomp"`
|
Thomp map[key]string `yaml:"thomp"`
|
||||||
Thugg *bool `yaml:"thugg"`
|
Thugg *bool `yaml:"thugg"`
|
||||||
|
Throo *float32 `yaml:"throo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 := test1low{
|
t2 := test1low{
|
||||||
@@ -922,6 +928,40 @@ func TestNewNodeBuilder_TestRenderZero(t *testing.T) {
|
|||||||
assert.Equal(t, desired, strings.TrimSpace(string(data)))
|
assert.Equal(t, desired, strings.TrimSpace(string(data)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestNewNodeBuilder_TestRenderZero_Float(t *testing.T) {
|
||||||
|
|
||||||
|
f := 0.0
|
||||||
|
t1 := test1{
|
||||||
|
Throo: &f,
|
||||||
|
}
|
||||||
|
|
||||||
|
nb := NewNodeBuilder(&t1, &t1)
|
||||||
|
node := nb.Render()
|
||||||
|
|
||||||
|
data, _ := yaml.Marshal(node)
|
||||||
|
|
||||||
|
desired := `throo: 0`
|
||||||
|
|
||||||
|
assert.Equal(t, desired, strings.TrimSpace(string(data)))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNewNodeBuilder_TestRenderZero_Float_NotZero(t *testing.T) {
|
||||||
|
|
||||||
|
f := 0.12
|
||||||
|
t1 := test1{
|
||||||
|
Throo: &f,
|
||||||
|
}
|
||||||
|
|
||||||
|
nb := NewNodeBuilder(&t1, &t1)
|
||||||
|
node := nb.Render()
|
||||||
|
|
||||||
|
data, _ := yaml.Marshal(node)
|
||||||
|
|
||||||
|
desired := `throo: 0.12`
|
||||||
|
|
||||||
|
assert.Equal(t, desired, strings.TrimSpace(string(data)))
|
||||||
|
}
|
||||||
|
|
||||||
func TestNewNodeBuilder_TestRenderServerVariableSimulation(t *testing.T) {
|
func TestNewNodeBuilder_TestRenderServerVariableSimulation(t *testing.T) {
|
||||||
|
|
||||||
t1 := test1{
|
t1 := test1{
|
||||||
@@ -962,6 +1002,7 @@ func TestNewNodeBuilder_ShouldHaveNotDoneTestsLikeThisOhWell(t *testing.T) {
|
|||||||
type t1low struct {
|
type t1low struct {
|
||||||
Thril low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*key]]
|
Thril low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*key]]
|
||||||
Thugg *bool `yaml:"thugg"`
|
Thugg *bool `yaml:"thugg"`
|
||||||
|
Throo *float32 `yaml:"throo"`
|
||||||
}
|
}
|
||||||
|
|
||||||
t1 := test1{
|
t1 := test1{
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -36,7 +37,7 @@ options:
|
|||||||
|
|
||||||
var n v2.PathItem
|
var n v2.PathItem
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewPathItem(&n)
|
r := NewPathItem(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v2low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2low "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
@@ -34,7 +35,7 @@ func NewPaths(paths *v2low.Paths) *Paths {
|
|||||||
pathItems.Set(result.key, result.result)
|
pathItems.Set(result.key, result.result)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = orderedmap.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v2low.PathItem], asyncResult[*PathItem]](
|
_ = datamodel.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v2low.PathItem], asyncResult[*PathItem]](
|
||||||
paths.PathItems, translateFunc, resultFunc,
|
paths.PathItems, translateFunc, resultFunc,
|
||||||
)
|
)
|
||||||
p.PathItems = pathItems
|
p.PathItems = pathItems
|
||||||
|
|||||||
@@ -4,22 +4,23 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
"github.com/pb33f/libopenapi/orderedmap"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
|
||||||
"io/ioutil"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var doc *v2.Swagger
|
var doc *v2.Swagger
|
||||||
|
|
||||||
func initTest() {
|
func initTest() {
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
data, _ := os.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
doc, err = v2.CreateDocument(info)
|
doc, err = v2.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ func TestCallback_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Callback
|
var n v3.Callback
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewCallback(&n)
|
r := NewCallback(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
highbase "github.com/pb33f/libopenapi/datamodel/high/base"
|
||||||
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
lowmodel "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -121,7 +122,7 @@ func buildComponent[IN any, OUT any](inMap orderedmap.Map[lowmodel.KeyReference[
|
|||||||
outMap.Set(value.key, value.res)
|
outMap.Set(value.key, value.res)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = orderedmap.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// buildSchema builds a schema from low level structs.
|
// buildSchema builds a schema from low level structs.
|
||||||
@@ -139,7 +140,7 @@ func buildSchema(inMap orderedmap.Map[lowmodel.KeyReference[string], lowmodel.Va
|
|||||||
outMap.Set(value.key, value.res)
|
outMap.Set(value.key, value.res)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = orderedmap.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
_ = datamodel.TranslateMapParallel(inMap, translateFunc, resultFunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GoLow returns the low-level Components instance used to create the high-level one.
|
// GoLow returns the low-level Components instance used to create the high-level one.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -48,7 +49,7 @@ func TestComponents_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Components
|
var n v3.Components
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewComponents(&n)
|
r := NewComponents(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -91,6 +91,10 @@ type Document struct {
|
|||||||
//
|
//
|
||||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||||
Index *index.SpecIndex `json:"-" yaml:"-"`
|
Index *index.SpecIndex `json:"-" yaml:"-"`
|
||||||
|
|
||||||
|
// Rolodex is the low-level rolodex used when creating this document.
|
||||||
|
// This in an internal structure and not part of the OpenAPI schema.
|
||||||
|
Rolodex *index.Rolodex `json:"-" yaml:"-"`
|
||||||
low *low.Document
|
low *low.Document
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,17 +5,25 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
v2 "github.com/pb33f/libopenapi/datamodel/high/v2"
|
||||||
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
lowv2 "github.com/pb33f/libopenapi/datamodel/low/v2"
|
||||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/orderedmap"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
var lowDoc *lowv3.Document
|
var lowDoc *lowv3.Document
|
||||||
@@ -23,7 +31,7 @@ var lowDoc *lowv3.Document
|
|||||||
func initTest() {
|
func initTest() {
|
||||||
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -221,7 +229,7 @@ func TestNewDocument_Components_Schemas(t *testing.T) {
|
|||||||
|
|
||||||
d := h.Components.Schemas.GetOrZero("Drink")
|
d := h.Components.Schemas.GetOrZero("Drink")
|
||||||
assert.Len(t, d.Schema().Required, 2)
|
assert.Len(t, d.Schema().Required, 2)
|
||||||
assert.True(t, d.Schema().AdditionalProperties.(bool))
|
assert.True(t, d.Schema().AdditionalProperties.B)
|
||||||
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
|
assert.Equal(t, "drinkType", d.Schema().Discriminator.PropertyName)
|
||||||
assert.Equal(t, "some value", d.Schema().Discriminator.Mapping["drink"])
|
assert.Equal(t, "some value", d.Schema().Discriminator.Mapping["drink"])
|
||||||
assert.Equal(t, 516, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
|
assert.Equal(t, 516, d.Schema().Discriminator.GoLow().PropertyName.ValueNode.Line)
|
||||||
@@ -378,15 +386,14 @@ func testBurgerShop(t *testing.T, h *Document, checkLines bool) {
|
|||||||
assert.Equal(t, 310, okResp.Links.GetOrZero("LocateBurger").GoLow().OperationId.ValueNode.Line)
|
assert.Equal(t, 310, okResp.Links.GetOrZero("LocateBurger").GoLow().OperationId.ValueNode.Line)
|
||||||
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
assert.Equal(t, 118, burgersOp.Post.Security[0].GoLow().Requirements.ValueNode.Line)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestStripeAsDoc(t *testing.T) {
|
func TestStripeAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
assert.Len(t, err, 3)
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
}
|
}
|
||||||
@@ -394,18 +401,18 @@ func TestStripeAsDoc(t *testing.T) {
|
|||||||
func TestK8sAsDoc(t *testing.T) {
|
func TestK8sAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/k8s.json")
|
data, _ := os.ReadFile("../../../test_specs/k8s.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowSwag, err := lowv2.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowSwag, err := lowv2.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
d := v2.NewSwaggerDocument(lowSwag)
|
d := v2.NewSwaggerDocument(lowSwag)
|
||||||
assert.Len(t, err, 0)
|
assert.Len(t, utils.UnwrapErrors(err), 0)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAsanaAsDoc(t *testing.T) {
|
func TestAsanaAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/asana.yaml")
|
data, _ := os.ReadFile("../../../test_specs/asana.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
}
|
}
|
||||||
@@ -414,10 +421,53 @@ func TestAsanaAsDoc(t *testing.T) {
|
|||||||
assert.Equal(t, 118, orderedmap.Len(d.Paths.PathItems))
|
assert.Equal(t, 118, orderedmap.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,
|
||||||
|
Logger: slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
|
Level: slog.LevelDebug,
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
|
||||||
|
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, d.Paths.PathItems.Len())
|
||||||
|
}
|
||||||
|
|
||||||
func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
data, _ := os.ReadFile("../../../test_specs/digitalocean.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
|
|
||||||
baseURL, _ := url.Parse("https://raw.githubusercontent.com/digitalocean/openapi/82e1d558e15a59edc1d47d2c5544e7138f5b3cbf/specification")
|
baseURL, _ := url.Parse("https://raw.githubusercontent.com/digitalocean/openapi/82e1d558e15a59edc1d47d2c5544e7138f5b3cbf/specification")
|
||||||
config := datamodel.DocumentConfiguration{
|
config := datamodel.DocumentConfiguration{
|
||||||
@@ -426,24 +476,68 @@ func TestDigitalOceanAsDocFromSHA(t *testing.T) {
|
|||||||
BaseURL: baseURL,
|
BaseURL: baseURL,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if os.Getenv("GH_PAT") != "" {
|
||||||
|
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("GH_PAT")))
|
||||||
|
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, d.Paths.PathItems.Len())
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
}
|
||||||
|
|
||||||
|
config.Logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
|
Level: slog.LevelError,
|
||||||
|
}))
|
||||||
|
|
||||||
|
if os.Getenv("GH_PAT") != "" {
|
||||||
|
client := &http.Client{
|
||||||
|
Timeout: time.Second * 60,
|
||||||
|
}
|
||||||
|
config.RemoteURLHandler = func(url string) (*http.Response, error) {
|
||||||
|
request, _ := http.NewRequest(http.MethodGet, url, nil)
|
||||||
|
request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", os.Getenv("GITHUB_TOKEN")))
|
||||||
|
return client.Do(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &config)
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &config)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
for e := range err {
|
er := utils.UnwrapErrors(err)
|
||||||
fmt.Println(err[e])
|
for e := range er {
|
||||||
|
fmt.Printf("Reported Error: %s\n", er[e])
|
||||||
}
|
}
|
||||||
panic("broken something")
|
|
||||||
}
|
}
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lowDoc)
|
||||||
assert.NotNil(t, d)
|
assert.NotNil(t, d)
|
||||||
assert.Equal(t, 183, orderedmap.Len(d.Paths.PathItems))
|
assert.Equal(t, 183, orderedmap.Len(d.Paths.PathItems))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPetstoreAsDoc(t *testing.T) {
|
func TestPetstoreAsDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
}
|
}
|
||||||
@@ -455,16 +549,15 @@ func TestPetstoreAsDoc(t *testing.T) {
|
|||||||
func TestCircularReferencesDoc(t *testing.T) {
|
func TestCircularReferencesDoc(t *testing.T) {
|
||||||
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lDoc, err := lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
assert.Len(t, err, 3)
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
d := NewDocument(lowDoc)
|
d := NewDocument(lDoc)
|
||||||
assert.Len(t, d.Components.Schemas, 9)
|
assert.Len(t, d.Components.Schemas, 9)
|
||||||
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
assert.Len(t, d.Index.GetCircularReferences(), 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalYAML(t *testing.T) {
|
func TestDocument_MarshalYAML(t *testing.T) {
|
||||||
|
|
||||||
// create a new document
|
// create a new document
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
@@ -473,20 +566,18 @@ func TestDocument_MarshalYAML(t *testing.T) {
|
|||||||
r, _ := h.Render()
|
r, _ := h.Render()
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo(r)
|
info, _ := datamodel.ExtractSpecInfo(r)
|
||||||
lDoc, e := lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lDoc, e := lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
|
|
||||||
highDoc := NewDocument(lDoc)
|
highDoc := NewDocument(lDoc)
|
||||||
testBurgerShop(t, highDoc, false)
|
testBurgerShop(t, highDoc, false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalIndention(t *testing.T) {
|
func TestDocument_MarshalIndention(t *testing.T) {
|
||||||
|
|
||||||
data, _ := os.ReadFile("../../../test_specs/single-definition.yaml")
|
data, _ := os.ReadFile("../../../test_specs/single-definition.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
|
|
||||||
highDoc := NewDocument(lowDoc)
|
highDoc := NewDocument(lowDoc)
|
||||||
rendered := highDoc.RenderWithIndention(2)
|
rendered := highDoc.RenderWithIndention(2)
|
||||||
@@ -496,15 +587,13 @@ func TestDocument_MarshalIndention(t *testing.T) {
|
|||||||
rendered = highDoc.RenderWithIndention(4)
|
rendered = highDoc.RenderWithIndention(4)
|
||||||
|
|
||||||
assert.NotEqual(t, string(data), strings.TrimSpace(string(rendered)))
|
assert.NotEqual(t, string(data), strings.TrimSpace(string(rendered)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalIndention_Error(t *testing.T) {
|
func TestDocument_MarshalIndention_Error(t *testing.T) {
|
||||||
|
|
||||||
data, _ := os.ReadFile("../../../test_specs/single-definition.yaml")
|
data, _ := os.ReadFile("../../../test_specs/single-definition.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
|
|
||||||
highDoc := NewDocument(lowDoc)
|
highDoc := NewDocument(lowDoc)
|
||||||
rendered := highDoc.RenderWithIndention(2)
|
rendered := highDoc.RenderWithIndention(2)
|
||||||
@@ -514,15 +603,13 @@ func TestDocument_MarshalIndention_Error(t *testing.T) {
|
|||||||
rendered = highDoc.RenderWithIndention(4)
|
rendered = highDoc.RenderWithIndention(4)
|
||||||
|
|
||||||
assert.NotEqual(t, string(data), strings.TrimSpace(string(rendered)))
|
assert.NotEqual(t, string(data), strings.TrimSpace(string(rendered)))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalJSON(t *testing.T) {
|
func TestDocument_MarshalJSON(t *testing.T) {
|
||||||
|
|
||||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
|
|
||||||
highDoc := NewDocument(lowDoc)
|
highDoc := NewDocument(lowDoc)
|
||||||
|
|
||||||
@@ -530,7 +617,7 @@ func TestDocument_MarshalJSON(t *testing.T) {
|
|||||||
|
|
||||||
// now read back in the JSON
|
// now read back in the JSON
|
||||||
info, _ = datamodel.ExtractSpecInfo(rendered)
|
info, _ = datamodel.ExtractSpecInfo(rendered)
|
||||||
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lowDoc, _ = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
newDoc := NewDocument(lowDoc)
|
newDoc := NewDocument(lowDoc)
|
||||||
|
|
||||||
assert.Equal(t, orderedmap.Len(newDoc.Paths.PathItems), orderedmap.Len(highDoc.Paths.PathItems))
|
assert.Equal(t, orderedmap.Len(newDoc.Paths.PathItems), orderedmap.Len(highDoc.Paths.PathItems))
|
||||||
@@ -538,7 +625,6 @@ func TestDocument_MarshalJSON(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalYAMLInline(t *testing.T) {
|
func TestDocument_MarshalYAMLInline(t *testing.T) {
|
||||||
|
|
||||||
// create a new document
|
// create a new document
|
||||||
initTest()
|
initTest()
|
||||||
h := NewDocument(lowDoc)
|
h := NewDocument(lowDoc)
|
||||||
@@ -547,16 +633,14 @@ func TestDocument_MarshalYAMLInline(t *testing.T) {
|
|||||||
r, _ := h.RenderInline()
|
r, _ := h.RenderInline()
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo(r)
|
info, _ := datamodel.ExtractSpecInfo(r)
|
||||||
lDoc, e := lowv3.CreateDocumentFromConfig(info, datamodel.NewOpenDocumentConfiguration())
|
lDoc, e := lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
assert.Nil(t, e)
|
assert.Nil(t, e)
|
||||||
|
|
||||||
highDoc := NewDocument(lDoc)
|
highDoc := NewDocument(lDoc)
|
||||||
testBurgerShop(t, highDoc, false)
|
testBurgerShop(t, highDoc, false)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalYAML_TestRefs(t *testing.T) {
|
func TestDocument_MarshalYAML_TestRefs(t *testing.T) {
|
||||||
|
|
||||||
// create a new document
|
// create a new document
|
||||||
yml := `openapi: 3.1.0
|
yml := `openapi: 3.1.0
|
||||||
paths:
|
paths:
|
||||||
@@ -617,7 +701,7 @@ components:
|
|||||||
numPatties: 1`
|
numPatties: 1`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -634,7 +718,6 @@ components:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalYAML_TestParamRefs(t *testing.T) {
|
func TestDocument_MarshalYAML_TestParamRefs(t *testing.T) {
|
||||||
|
|
||||||
// create a new document
|
// create a new document
|
||||||
yml := `openapi: 3.1.0
|
yml := `openapi: 3.1.0
|
||||||
paths:
|
paths:
|
||||||
@@ -671,7 +754,7 @@ components:
|
|||||||
required: true`
|
required: true`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
@@ -687,7 +770,6 @@ components:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestDocument_MarshalYAML_TestModifySchemas(t *testing.T) {
|
func TestDocument_MarshalYAML_TestModifySchemas(t *testing.T) {
|
||||||
|
|
||||||
// create a new document
|
// create a new document
|
||||||
yml := `openapi: 3.1.0
|
yml := `openapi: 3.1.0
|
||||||
components:
|
components:
|
||||||
@@ -700,7 +782,7 @@ components:
|
|||||||
`
|
`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: true,
|
AllowFileReferences: true,
|
||||||
AllowRemoteReferences: true,
|
AllowRemoteReferences: true,
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"context"
|
||||||
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -18,9 +19,9 @@ import (
|
|||||||
|
|
||||||
func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
func TestMediaType_MarshalYAMLInline(t *testing.T) {
|
||||||
// load the petstore spec
|
// load the petstore spec
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
@@ -108,9 +109,9 @@ example: testing a nice mutation`
|
|||||||
|
|
||||||
func TestMediaType_MarshalYAML(t *testing.T) {
|
func TestMediaType_MarshalYAML(t *testing.T) {
|
||||||
// load the petstore spec
|
// load the petstore spec
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
lowDoc, err = v3.CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
@@ -161,7 +162,7 @@ func TestMediaType_Examples(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.MediaType
|
var n v3.MediaType
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewMediaType(&n)
|
r := NewMediaType(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ clientCredentials:
|
|||||||
|
|
||||||
var n v3.OAuthFlows
|
var n v3.OAuthFlows
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOAuthFlows(&n)
|
r := NewOAuthFlows(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -43,7 +44,7 @@ callbacks:
|
|||||||
|
|
||||||
var n v3.Operation
|
var n v3.Operation
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOperation(&n)
|
r := NewOperation(&n)
|
||||||
|
|
||||||
@@ -140,7 +141,7 @@ security: []`
|
|||||||
|
|
||||||
var n v3.Operation
|
var n v3.Operation
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOperation(&n)
|
r := NewOperation(&n)
|
||||||
|
|
||||||
@@ -158,7 +159,7 @@ func TestOperation_NoSecurity(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Operation
|
var n v3.Operation
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewOperation(&n)
|
r := NewOperation(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
lowv3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
@@ -15,22 +16,19 @@ import (
|
|||||||
// An example of how to create a new high-level OpenAPI 3+ document from an OpenAPI specification.
|
// An example of how to create a new high-level OpenAPI 3+ document from an OpenAPI specification.
|
||||||
func Example_createHighLevelOpenAPIDocument() {
|
func Example_createHighLevelOpenAPIDocument() {
|
||||||
// Load in an OpenAPI 3+ specification as a byte slice.
|
// Load in an OpenAPI 3+ specification as a byte slice.
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
|
|
||||||
// Create a new *datamodel.SpecInfo from bytes.
|
// Create a new *datamodel.SpecInfo from bytes.
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
var err []error
|
var err error
|
||||||
|
|
||||||
// Create a new low-level Document, capture any errors thrown during creation.
|
// Create a new low-level Document, capture any errors thrown during creation.
|
||||||
lowDoc, err = lowv3.CreateDocument(info)
|
lowDoc, err = lowv3.CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
|
|
||||||
// Get upset if any errors were thrown.
|
// Get upset if any errors were thrown.
|
||||||
if len(err) > 0 {
|
for i := range utils.UnwrapErrors(err) {
|
||||||
for i := range err {
|
fmt.Printf("error: %v", i)
|
||||||
fmt.Printf("error: %e", err[i])
|
|
||||||
}
|
|
||||||
panic("something went wrong")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a high-level Document from the low-level one.
|
// Create a high-level Document from the low-level one.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ func TestPathItem(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.PathItem
|
var n v3.PathItem
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewPathItem(&n)
|
r := NewPathItem(&n)
|
||||||
|
|
||||||
@@ -62,7 +63,7 @@ trace:
|
|||||||
|
|
||||||
var n v3.PathItem
|
var n v3.PathItem
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewPathItem(&n)
|
r := NewPathItem(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ package v3
|
|||||||
import (
|
import (
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
@@ -45,7 +46,7 @@ func NewPaths(paths *v3low.Paths) *Paths {
|
|||||||
items.Set(value.key, value.value)
|
items.Set(value.key, value.value)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = orderedmap.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v3low.PathItem], pathItemResult](
|
_ = datamodel.TranslateMapParallel[low.KeyReference[string], low.ValueReference[*v3low.PathItem], pathItemResult](
|
||||||
paths.PathItems, translateFunc, resultFunc,
|
paths.PathItems, translateFunc, resultFunc,
|
||||||
)
|
)
|
||||||
p.PathItems = items
|
p.PathItems = items
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ func TestPaths_MarshalYAML(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
high := NewPaths(&n)
|
high := NewPaths(&n)
|
||||||
@@ -89,7 +90,7 @@ func TestPaths_MarshalYAMLInline(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
high := NewPaths(&n)
|
high := NewPaths(&n)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -39,7 +40,7 @@ links:
|
|||||||
|
|
||||||
var n v3.Response
|
var n v3.Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponse(&n)
|
r := NewResponse(&n)
|
||||||
|
|
||||||
@@ -70,7 +71,7 @@ links:
|
|||||||
|
|
||||||
var n v3.Response
|
var n v3.Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponse(&n)
|
r := NewResponse(&n)
|
||||||
|
|
||||||
@@ -98,7 +99,7 @@ links:
|
|||||||
|
|
||||||
var n v3.Response
|
var n v3.Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponse(&n)
|
r := NewResponse(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
|
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/high"
|
"github.com/pb33f/libopenapi/datamodel/high"
|
||||||
lowbase "github.com/pb33f/libopenapi/datamodel/low"
|
lowbase "github.com/pb33f/libopenapi/datamodel/low"
|
||||||
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
low "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
@@ -47,11 +48,6 @@ func NewResponses(responses *low.Responses) *Responses {
|
|||||||
}
|
}
|
||||||
codes := orderedmap.New[string, *Response]()
|
codes := orderedmap.New[string, *Response]()
|
||||||
|
|
||||||
type respRes struct {
|
|
||||||
code string
|
|
||||||
resp *Response
|
|
||||||
}
|
|
||||||
|
|
||||||
translateFunc := func(pair orderedmap.Pair[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response]]) (asyncResult[*Response], error) {
|
translateFunc := func(pair orderedmap.Pair[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response]]) (asyncResult[*Response], error) {
|
||||||
return asyncResult[*Response]{
|
return asyncResult[*Response]{
|
||||||
key: pair.Key().Value,
|
key: pair.Key().Value,
|
||||||
@@ -62,7 +58,7 @@ func NewResponses(responses *low.Responses) *Responses {
|
|||||||
codes.Set(value.key, value.result)
|
codes.Set(value.key, value.result)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
_ = orderedmap.TranslateMapParallel[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response], asyncResult[*Response]](responses.Codes, translateFunc, resultFunc)
|
_ = datamodel.TranslateMapParallel[lowbase.KeyReference[string], lowbase.ValueReference[*low.Response]](responses.Codes, translateFunc, resultFunc)
|
||||||
r.Codes = codes
|
r.Codes = codes
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
@@ -126,8 +122,10 @@ func (r *Responses) MarshalYAML() (interface{}, error) {
|
|||||||
label = extNode.Content[u].Value
|
label = extNode.Content[u].Value
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &responseItem{nil, label,
|
mapped = append(mapped, &responseItem{
|
||||||
extNode.Content[u].Line, extNode.Content[u]})
|
nil, label,
|
||||||
|
extNode.Content[u].Line, extNode.Content[u],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -183,8 +181,10 @@ func (r *Responses) MarshalYAMLInline() (interface{}, error) {
|
|||||||
label = extNode.Content[u].Value
|
label = extNode.Content[u].Value
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
mapped = append(mapped, &responseItem{nil, label,
|
mapped = append(mapped, &responseItem{
|
||||||
extNode.Content[u].Line, extNode.Content[u]})
|
nil, label,
|
||||||
|
extNode.Content[u].Line, extNode.Content[u],
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ func TestNewResponses(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Responses
|
var n v3.Responses
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponses(&n)
|
r := NewResponses(&n)
|
||||||
|
|
||||||
@@ -60,7 +61,7 @@ func TestResponses_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Responses
|
var n v3.Responses
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponses(&n)
|
r := NewResponses(&n)
|
||||||
|
|
||||||
@@ -90,7 +91,7 @@ func TestResponses_MarshalYAMLInline(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.Responses
|
var n v3.Responses
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewResponses(&n)
|
r := NewResponses(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
v3 "github.com/pb33f/libopenapi/datamodel/low/v3"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -31,7 +32,7 @@ func TestSecurityScheme_MarshalYAML(t *testing.T) {
|
|||||||
|
|
||||||
var n v3.SecurityScheme
|
var n v3.SecurityScheme
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
r := NewSecurityScheme(&n)
|
r := NewSecurityScheme(&n)
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -23,7 +24,7 @@ type Contact struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build is not implemented for Contact (there is nothing to build).
|
// Build is not implemented for Contact (there is nothing to build).
|
||||||
func (c *Contact) Build(_, _ *yaml.Node, _ *index.SpecIndex) error {
|
func (c *Contact) Build(_ context.Context, _, _ *yaml.Node, _ *index.SpecIndex) error {
|
||||||
c.Reference = new(low.Reference)
|
c.Reference = new(low.Reference)
|
||||||
// not implemented.
|
// not implemented.
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -61,7 +62,7 @@ func (ex *Example) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build extracts extensions and example value
|
// Build extracts extensions and example value
|
||||||
func (ex *Example) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ex *Example) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ex.Reference = new(low.Reference)
|
ex.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -26,7 +27,7 @@ x-cake: hot`
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "hot", n.Summary.Value)
|
assert.Equal(t, "hot", n.Summary.Value)
|
||||||
assert.Equal(t, "cakes", n.Description.Value)
|
assert.Equal(t, "cakes", n.Description.Value)
|
||||||
@@ -52,7 +53,7 @@ x-cake: hot`
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "hot", n.Summary.Value)
|
assert.Equal(t, "hot", n.Summary.Value)
|
||||||
assert.Equal(t, "cakes", n.Description.Value)
|
assert.Equal(t, "cakes", n.Description.Value)
|
||||||
@@ -79,7 +80,7 @@ value:
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "hot", n.Summary.Value)
|
assert.Equal(t, "hot", n.Summary.Value)
|
||||||
assert.Equal(t, "cakes", n.Description.Value)
|
assert.Equal(t, "cakes", n.Description.Value)
|
||||||
@@ -110,7 +111,7 @@ value:
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "hot", n.Summary.Value)
|
assert.Equal(t, "hot", n.Summary.Value)
|
||||||
assert.Equal(t, "cakes", n.Description.Value)
|
assert.Equal(t, "cakes", n.Description.Value)
|
||||||
@@ -142,7 +143,7 @@ func TestExample_Build_Success_MergeNode(t *testing.T) {
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "hot", n.Summary.Value)
|
assert.Equal(t, "hot", n.Summary.Value)
|
||||||
assert.Equal(t, "cakes", n.Description.Value)
|
assert.Equal(t, "cakes", n.Description.Value)
|
||||||
@@ -237,8 +238,8 @@ x-burger: nice`
|
|||||||
var rDoc Example
|
var rDoc Example
|
||||||
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
||||||
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
||||||
_ = lDoc.Build(nil, lNode.Content[0], nil)
|
_ = lDoc.Build(context.Background(), nil, lNode.Content[0], nil)
|
||||||
_ = rDoc.Build(nil, rNode.Content[0], nil)
|
_ = rDoc.Build(context.Background(), nil, rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
||||||
assert.Len(t, lDoc.GetExtensions(), 1)
|
assert.Len(t, lDoc.GetExtensions(), 1)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -33,7 +34,7 @@ func (ex *ExternalDoc) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions from the ExternalDoc instance.
|
// Build will extract extensions from the ExternalDoc instance.
|
||||||
func (ex *ExternalDoc) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ex *ExternalDoc) Build(_ context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ex.Reference = new(low.Reference)
|
ex.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -23,7 +24,7 @@ func TestExternalDoc_FindExtension(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "cake", n.FindExtension("x-fish").Value)
|
assert.Equal(t, "cake", n.FindExtension("x-fish").Value)
|
||||||
|
|
||||||
@@ -44,7 +45,7 @@ x-b33f: princess`
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "https://pb33f.io", n.URL.Value)
|
assert.Equal(t, "https://pb33f.io", n.URL.Value)
|
||||||
assert.Equal(t, "the ranch", n.Description.Value)
|
assert.Equal(t, "the ranch", n.Description.Value)
|
||||||
@@ -73,8 +74,8 @@ description: the ranch`
|
|||||||
var rDoc ExternalDoc
|
var rDoc ExternalDoc
|
||||||
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
||||||
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
||||||
_ = lDoc.Build(nil, lNode.Content[0], nil)
|
_ = lDoc.Build(context.Background(), nil, lNode.Content[0], nil)
|
||||||
_ = rDoc.Build(nil, rNode.Content[0], nil)
|
_ = rDoc.Build(context.Background(), nil, rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
||||||
assert.Len(t, lDoc.GetExtensions(), 1)
|
assert.Len(t, lDoc.GetExtensions(), 1)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
@@ -45,18 +46,18 @@ func (i *Info) GetExtensions() map[low.KeyReference[string]]low.ValueReference[a
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract out the Contact and Info objects from the supplied root node.
|
// Build will extract out the Contact and Info objects from the supplied root node.
|
||||||
func (i *Info) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (i *Info) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
i.Reference = new(low.Reference)
|
i.Reference = new(low.Reference)
|
||||||
i.Extensions = low.ExtractExtensions(root)
|
i.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract contact
|
// extract contact
|
||||||
contact, _ := low.ExtractObject[*Contact](ContactLabel, root, idx)
|
contact, _ := low.ExtractObject[*Contact](ctx, ContactLabel, root, idx)
|
||||||
i.Contact = contact
|
i.Contact = contact
|
||||||
|
|
||||||
// extract license
|
// extract license
|
||||||
lic, _ := low.ExtractObject[*License](LicenseLabel, root, idx)
|
lic, _ := low.ExtractObject[*License](ctx, LicenseLabel, root, idx)
|
||||||
i.License = lic
|
i.License = lic
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -34,7 +35,7 @@ x-cli-name: pizza cli`
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "pizza", n.Title.Value)
|
assert.Equal(t, "pizza", n.Title.Value)
|
||||||
@@ -61,13 +62,13 @@ x-cli-name: pizza cli`
|
|||||||
|
|
||||||
func TestContact_Build(t *testing.T) {
|
func TestContact_Build(t *testing.T) {
|
||||||
n := &Contact{}
|
n := &Contact{}
|
||||||
k := n.Build(nil, nil, nil)
|
k := n.Build(context.Background(), nil, nil, nil)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLicense_Build(t *testing.T) {
|
func TestLicense_Build(t *testing.T) {
|
||||||
n := &License{}
|
n := &License{}
|
||||||
k := n.Build(nil, nil, nil)
|
k := n.Build(context.Background(), nil, nil, nil)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +108,8 @@ x-b33f: princess`
|
|||||||
var rDoc Info
|
var rDoc Info
|
||||||
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
||||||
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
||||||
_ = lDoc.Build(nil, lNode.Content[0], nil)
|
_ = lDoc.Build(context.Background(), nil, lNode.Content[0], nil)
|
||||||
_ = rDoc.Build(nil, rNode.Content[0], nil)
|
_ = rDoc.Build(context.Background(), nil, rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -25,7 +26,7 @@ type License struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build out a license, complain if both a URL and identifier are present as they are mutually exclusive
|
// Build out a license, complain if both a URL and identifier are present as they are mutually exclusive
|
||||||
func (l *License) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (l *License) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
l.Reference = new(low.Reference)
|
l.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -70,7 +71,7 @@ description: the ranch`
|
|||||||
var lDoc License
|
var lDoc License
|
||||||
err := low.BuildModel(lNode.Content[0], &lDoc)
|
err := low.BuildModel(lNode.Content[0], &lDoc)
|
||||||
|
|
||||||
err = lDoc.Build(nil, lNode.Content[0], nil)
|
err = lDoc.Build(context.Background(), nil, lNode.Content[0], nil)
|
||||||
|
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
assert.Equal(t, "license cannot have both a URL and an identifier, they are mutually exclusive", err.Error())
|
assert.Equal(t, "license cannot have both a URL and an identifier, they are mutually exclusive", err.Error())
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -101,7 +101,7 @@ type Schema struct {
|
|||||||
PatternProperties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
PatternProperties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||||
PropertyNames low.NodeReference[*SchemaProxy]
|
PropertyNames low.NodeReference[*SchemaProxy]
|
||||||
UnevaluatedItems low.NodeReference[*SchemaProxy]
|
UnevaluatedItems low.NodeReference[*SchemaProxy]
|
||||||
UnevaluatedProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, *bool]]
|
UnevaluatedProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]
|
||||||
Anchor low.NodeReference[string]
|
Anchor low.NodeReference[string]
|
||||||
|
|
||||||
// Compatible with all versions
|
// Compatible with all versions
|
||||||
@@ -122,7 +122,7 @@ type Schema struct {
|
|||||||
Enum low.NodeReference[[]low.ValueReference[any]]
|
Enum low.NodeReference[[]low.ValueReference[any]]
|
||||||
Not low.NodeReference[*SchemaProxy]
|
Not low.NodeReference[*SchemaProxy]
|
||||||
Properties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
Properties low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
|
||||||
AdditionalProperties low.NodeReference[any]
|
AdditionalProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]
|
||||||
Description low.NodeReference[string]
|
Description low.NodeReference[string]
|
||||||
ContentEncoding low.NodeReference[string]
|
ContentEncoding low.NodeReference[string]
|
||||||
ContentMediaType low.NodeReference[string]
|
ContentMediaType low.NodeReference[string]
|
||||||
@@ -139,6 +139,9 @@ type Schema struct {
|
|||||||
|
|
||||||
// Parent Proxy refers back to the low level SchemaProxy that is proxying this schema.
|
// Parent Proxy refers back to the low level SchemaProxy that is proxying this schema.
|
||||||
ParentProxy *SchemaProxy
|
ParentProxy *SchemaProxy
|
||||||
|
|
||||||
|
// Index is a reference to the SpecIndex that was used to build this schema.
|
||||||
|
Index *index.SpecIndex
|
||||||
*low.Reference
|
*low.Reference
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,54 +193,8 @@ func (s *Schema) Hash() [32]byte {
|
|||||||
d = append(d, fmt.Sprint(s.MinProperties.Value))
|
d = append(d, fmt.Sprint(s.MinProperties.Value))
|
||||||
}
|
}
|
||||||
if !s.AdditionalProperties.IsEmpty() {
|
if !s.AdditionalProperties.IsEmpty() {
|
||||||
|
|
||||||
// check type of properties, if we have a low level map, we need to hash the values in a repeatable
|
|
||||||
// order.
|
|
||||||
to := reflect.TypeOf(s.AdditionalProperties.Value)
|
|
||||||
vo := reflect.ValueOf(s.AdditionalProperties.Value)
|
|
||||||
var values []string
|
|
||||||
switch to.Kind() {
|
|
||||||
case reflect.Slice:
|
|
||||||
for i := 0; i < vo.Len(); i++ {
|
|
||||||
vn := vo.Index(i).Interface()
|
|
||||||
|
|
||||||
if jh, ok := vn.(low.HasValueUnTyped); ok {
|
|
||||||
vn = jh.GetValueUntyped()
|
|
||||||
fg := reflect.TypeOf(vn)
|
|
||||||
gf := reflect.ValueOf(vn)
|
|
||||||
|
|
||||||
if fg.Kind() == reflect.Map {
|
|
||||||
for _, ky := range gf.MapKeys() {
|
|
||||||
hu := ky.Interface()
|
|
||||||
values = append(values, fmt.Sprintf("%s:%s", hu, low.GenerateHashString(gf.MapIndex(ky).Interface())))
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
values = append(values, fmt.Sprintf("%d:%s", i, low.GenerateHashString(vn)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sort.Strings(values)
|
|
||||||
d = append(d, strings.Join(values, "||"))
|
|
||||||
|
|
||||||
case reflect.Map:
|
|
||||||
for _, k := range vo.MapKeys() {
|
|
||||||
var x string
|
|
||||||
var l int
|
|
||||||
var v any
|
|
||||||
// extract key
|
|
||||||
if o, ok := k.Interface().(low.HasKeyNode); ok {
|
|
||||||
x = o.GetKeyNode().Value
|
|
||||||
l = o.GetKeyNode().Line
|
|
||||||
v = vo.MapIndex(k).Interface().(low.HasValueNodeUntyped).GetValueNode().Value
|
|
||||||
}
|
|
||||||
values = append(values, fmt.Sprintf("%d:%s:%s", l, x, low.GenerateHashString(v)))
|
|
||||||
}
|
|
||||||
sort.Strings(values)
|
|
||||||
d = append(d, strings.Join(values, "||"))
|
|
||||||
default:
|
|
||||||
d = append(d, low.GenerateHashString(s.AdditionalProperties.Value))
|
d = append(d, low.GenerateHashString(s.AdditionalProperties.Value))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if !s.Description.IsEmpty() {
|
if !s.Description.IsEmpty() {
|
||||||
d = append(d, fmt.Sprint(s.Description.Value))
|
d = append(d, fmt.Sprint(s.Description.Value))
|
||||||
}
|
}
|
||||||
@@ -535,12 +492,13 @@ func (s *Schema) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
// - UnevaluatedItems
|
// - UnevaluatedItems
|
||||||
// - UnevaluatedProperties
|
// - UnevaluatedProperties
|
||||||
// - Anchor
|
// - Anchor
|
||||||
func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Reference = new(low.Reference)
|
s.Reference = new(low.Reference)
|
||||||
|
s.Index = idx
|
||||||
if h, _, _ := utils.IsNodeRefValue(root); h {
|
if h, _, _ := utils.IsNodeRefValue(root); h {
|
||||||
ref, err := low.LocateRefNode(root, idx)
|
ref, _, err := low.LocateRefNode(root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
root = ref
|
root = ref
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -591,6 +549,28 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// determine exclusive minimum type, bool (3.0) or int (3.1)
|
// determine exclusive minimum type, bool (3.0) or int (3.1)
|
||||||
_, exMinLabel, exMinValue := utils.FindKeyNodeFullTop(ExclusiveMinimumLabel, root.Content)
|
_, exMinLabel, exMinValue := utils.FindKeyNodeFullTop(ExclusiveMinimumLabel, root.Content)
|
||||||
if exMinValue != nil {
|
if exMinValue != nil {
|
||||||
|
|
||||||
|
// if there is an index, determine if this a 3.0 or 3.1 schema
|
||||||
|
if idx != nil {
|
||||||
|
if idx.GetConfig().SpecInfo.VersionNumeric == 3.1 {
|
||||||
|
val, _ := strconv.ParseFloat(exMinValue.Value, 64)
|
||||||
|
s.ExclusiveMinimum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
||||||
|
KeyNode: exMinLabel,
|
||||||
|
ValueNode: exMinValue,
|
||||||
|
Value: &SchemaDynamicValue[bool, float64]{N: 1, B: val},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if idx.GetConfig().SpecInfo.VersionNumeric <= 3.0 {
|
||||||
|
val, _ := strconv.ParseBool(exMinValue.Value)
|
||||||
|
s.ExclusiveMinimum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
||||||
|
KeyNode: exMinLabel,
|
||||||
|
ValueNode: exMinValue,
|
||||||
|
Value: &SchemaDynamicValue[bool, float64]{N: 0, A: val},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// there is no index, so we have to determine the type based on the value
|
||||||
if utils.IsNodeBoolValue(exMinValue) {
|
if utils.IsNodeBoolValue(exMinValue) {
|
||||||
val, _ := strconv.ParseBool(exMinValue.Value)
|
val, _ := strconv.ParseBool(exMinValue.Value)
|
||||||
s.ExclusiveMinimum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
s.ExclusiveMinimum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
||||||
@@ -608,10 +588,33 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// determine exclusive maximum type, bool (3.0) or int (3.1)
|
// determine exclusive maximum type, bool (3.0) or int (3.1)
|
||||||
_, exMaxLabel, exMaxValue := utils.FindKeyNodeFullTop(ExclusiveMaximumLabel, root.Content)
|
_, exMaxLabel, exMaxValue := utils.FindKeyNodeFullTop(ExclusiveMaximumLabel, root.Content)
|
||||||
if exMaxValue != nil {
|
if exMaxValue != nil {
|
||||||
|
|
||||||
|
// if there is an index, determine if this a 3.0 or 3.1 schema
|
||||||
|
if idx != nil {
|
||||||
|
if idx.GetConfig().SpecInfo.VersionNumeric == 3.1 {
|
||||||
|
val, _ := strconv.ParseFloat(exMaxValue.Value, 64)
|
||||||
|
s.ExclusiveMaximum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
||||||
|
KeyNode: exMaxLabel,
|
||||||
|
ValueNode: exMaxValue,
|
||||||
|
Value: &SchemaDynamicValue[bool, float64]{N: 1, B: val},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if idx.GetConfig().SpecInfo.VersionNumeric <= 3.0 {
|
||||||
|
val, _ := strconv.ParseBool(exMaxValue.Value)
|
||||||
|
s.ExclusiveMaximum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
||||||
|
KeyNode: exMaxLabel,
|
||||||
|
ValueNode: exMaxValue,
|
||||||
|
Value: &SchemaDynamicValue[bool, float64]{N: 0, A: val},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// there is no index, so we have to determine the type based on the value
|
||||||
if utils.IsNodeBoolValue(exMaxValue) {
|
if utils.IsNodeBoolValue(exMaxValue) {
|
||||||
val, _ := strconv.ParseBool(exMaxValue.Value)
|
val, _ := strconv.ParseBool(exMaxValue.Value)
|
||||||
s.ExclusiveMaximum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
s.ExclusiveMaximum = low.NodeReference[*SchemaDynamicValue[bool, float64]]{
|
||||||
@@ -629,6 +632,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// handle schema reference type if set. (3.1)
|
// handle schema reference type if set. (3.1)
|
||||||
_, schemaRefLabel, schemaRefNode := utils.FindKeyNodeFullTop(SchemaTypeLabel, root.Content)
|
_, schemaRefLabel, schemaRefNode := utils.FindKeyNodeFullTop(SchemaTypeLabel, root.Content)
|
||||||
@@ -668,77 +672,24 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_, addPLabel, addPNode := utils.FindKeyNodeFullTop(AdditionalPropertiesLabel, root.Content)
|
// check additionalProperties type for schema or bool
|
||||||
if addPNode != nil {
|
addPropsIsBool := false
|
||||||
if utils.IsNodeMap(addPNode) || utils.IsNodeArray(addPNode) {
|
addPropsBoolValue := true
|
||||||
// check if this is a reference, or an inline schema.
|
_, addPLabel, addPValue := utils.FindKeyNodeFullTop(AdditionalPropertiesLabel, root.Content)
|
||||||
isRef, _, _ := utils.IsNodeRefValue(addPNode)
|
if addPValue != nil {
|
||||||
var sp *SchemaProxy
|
if utils.IsNodeBoolValue(addPValue) {
|
||||||
// now check if this object has a 'type' if so, it's a schema, if not... it's a random
|
addPropsIsBool = true
|
||||||
// object, and we should treat it as a raw map.
|
addPropsBoolValue, _ = strconv.ParseBool(addPValue.Value)
|
||||||
if _, v := utils.FindKeyNodeTop(TypeLabel, addPNode.Content); v != nil {
|
|
||||||
sp = &SchemaProxy{
|
|
||||||
kn: addPLabel,
|
|
||||||
vn: addPNode,
|
|
||||||
idx: idx,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if isRef {
|
if addPropsIsBool {
|
||||||
_, vn := utils.FindKeyNodeTop("$ref", addPNode.Content)
|
s.AdditionalProperties = low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]{
|
||||||
sp = &SchemaProxy{
|
Value: &SchemaDynamicValue[*SchemaProxy, bool]{
|
||||||
kn: addPLabel,
|
B: addPropsBoolValue,
|
||||||
vn: addPNode,
|
N: 1,
|
||||||
idx: idx,
|
},
|
||||||
isReference: true,
|
KeyNode: addPLabel,
|
||||||
referenceLookup: vn.Value,
|
ValueNode: addPValue,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if this is a reference, or a schema, we're done.
|
|
||||||
if sp != nil {
|
|
||||||
s.AdditionalProperties = low.NodeReference[any]{Value: sp, KeyNode: addPLabel, ValueNode: addPNode}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// if this is a map, collect all the keys and values.
|
|
||||||
if utils.IsNodeMap(addPNode) {
|
|
||||||
|
|
||||||
addProps := make(map[low.KeyReference[string]]low.ValueReference[any])
|
|
||||||
var label string
|
|
||||||
for g := range addPNode.Content {
|
|
||||||
if g%2 == 0 {
|
|
||||||
label = addPNode.Content[g].Value
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
addProps[low.KeyReference[string]{Value: label, KeyNode: addPNode.Content[g-1]}] = low.ValueReference[any]{Value: addPNode.Content[g].Value, ValueNode: addPNode.Content[g]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.AdditionalProperties = low.NodeReference[any]{Value: addProps, KeyNode: addPLabel, ValueNode: addPNode}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the node is an array, extract everything into a trackable structure
|
|
||||||
if utils.IsNodeArray(addPNode) {
|
|
||||||
var addProps []low.ValueReference[any]
|
|
||||||
|
|
||||||
// if this is an array or maps, encode the map items correctly.
|
|
||||||
for i := range addPNode.Content {
|
|
||||||
if utils.IsNodeMap(addPNode.Content[i]) {
|
|
||||||
var prop map[string]any
|
|
||||||
_ = addPNode.Content[i].Decode(&prop)
|
|
||||||
addProps = append(addProps,
|
|
||||||
low.ValueReference[any]{Value: prop, ValueNode: addPNode.Content[i]})
|
|
||||||
} else {
|
|
||||||
addProps = append(addProps,
|
|
||||||
low.ValueReference[any]{Value: addPNode.Content[i].Value, ValueNode: addPNode.Content[i]})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
s.AdditionalProperties = low.NodeReference[any]{Value: addProps, KeyNode: addPLabel, ValueNode: addPNode}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if utils.IsNodeBoolValue(addPNode) {
|
|
||||||
b, _ := strconv.ParseBool(addPNode.Value)
|
|
||||||
s.AdditionalProperties = low.NodeReference[any]{Value: b, KeyNode: addPLabel, ValueNode: addPNode}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -755,7 +706,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if extDocNode != nil {
|
if extDocNode != nil {
|
||||||
var exDoc ExternalDoc
|
var exDoc ExternalDoc
|
||||||
_ = low.BuildModel(extDocNode, &exDoc)
|
_ = low.BuildModel(extDocNode, &exDoc)
|
||||||
_ = exDoc.Build(extDocLabel, extDocNode, idx) // throws no errors, can't check for one.
|
_ = exDoc.Build(ctx, extDocLabel, extDocNode, idx) // throws no errors, can't check for one.
|
||||||
s.ExternalDocs = low.NodeReference[*ExternalDoc]{Value: &exDoc, KeyNode: extDocLabel, ValueNode: extDocNode}
|
s.ExternalDocs = low.NodeReference[*ExternalDoc]{Value: &exDoc, KeyNode: extDocLabel, ValueNode: extDocNode}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -770,7 +721,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle properties
|
// handle properties
|
||||||
props, err := buildPropertyMap(root, idx, PropertiesLabel)
|
props, err := buildPropertyMap(ctx, root, idx, PropertiesLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -779,7 +730,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle dependent schemas
|
// handle dependent schemas
|
||||||
props, err = buildPropertyMap(root, idx, DependentSchemasLabel)
|
props, err = buildPropertyMap(ctx, root, idx, DependentSchemasLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -788,7 +739,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle pattern properties
|
// handle pattern properties
|
||||||
props, err = buildPropertyMap(root, idx, PatternPropertiesLabel)
|
props, err = buildPropertyMap(ctx, root, idx, PatternPropertiesLabel)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -828,9 +779,9 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if unevalIsBool {
|
if unevalIsBool {
|
||||||
s.UnevaluatedProperties = low.NodeReference[*SchemaDynamicValue[*SchemaProxy, *bool]]{
|
s.UnevaluatedProperties = low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]{
|
||||||
Value: &SchemaDynamicValue[*SchemaProxy, *bool]{
|
Value: &SchemaDynamicValue[*SchemaProxy, bool]{
|
||||||
B: &unevalBoolValue,
|
B: unevalBoolValue,
|
||||||
N: 1,
|
N: 1,
|
||||||
},
|
},
|
||||||
KeyNode: unevalLabel,
|
KeyNode: unevalLabel,
|
||||||
@@ -839,7 +790,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var allOf, anyOf, oneOf, prefixItems []low.ValueReference[*SchemaProxy]
|
var allOf, anyOf, oneOf, prefixItems []low.ValueReference[*SchemaProxy]
|
||||||
var items, not, contains, sif, selse, sthen, propertyNames, unevalItems, unevalProperties low.ValueReference[*SchemaProxy]
|
var items, not, contains, sif, selse, sthen, propertyNames, unevalItems, unevalProperties, addProperties low.ValueReference[*SchemaProxy]
|
||||||
|
|
||||||
_, allOfLabel, allOfValue := utils.FindKeyNodeFullTop(AllOfLabel, root.Content)
|
_, allOfLabel, allOfValue := utils.FindKeyNodeFullTop(AllOfLabel, root.Content)
|
||||||
_, anyOfLabel, anyOfValue := utils.FindKeyNodeFullTop(AnyOfLabel, root.Content)
|
_, anyOfLabel, anyOfValue := utils.FindKeyNodeFullTop(AnyOfLabel, root.Content)
|
||||||
@@ -853,6 +804,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
_, propNamesLabel, propNamesValue := utils.FindKeyNodeFullTop(PropertyNamesLabel, root.Content)
|
_, propNamesLabel, propNamesValue := utils.FindKeyNodeFullTop(PropertyNamesLabel, root.Content)
|
||||||
_, unevalItemsLabel, unevalItemsValue := utils.FindKeyNodeFullTop(UnevaluatedItemsLabel, root.Content)
|
_, unevalItemsLabel, unevalItemsValue := utils.FindKeyNodeFullTop(UnevaluatedItemsLabel, root.Content)
|
||||||
_, unevalPropsLabel, unevalPropsValue := utils.FindKeyNodeFullTop(UnevaluatedPropertiesLabel, root.Content)
|
_, unevalPropsLabel, unevalPropsValue := utils.FindKeyNodeFullTop(UnevaluatedPropertiesLabel, root.Content)
|
||||||
|
_, addPropsLabel, addPropsValue := utils.FindKeyNodeFullTop(AdditionalPropertiesLabel, root.Content)
|
||||||
|
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
allOfChan := make(chan schemaProxyBuildResult)
|
allOfChan := make(chan schemaProxyBuildResult)
|
||||||
@@ -868,6 +820,7 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
propNamesChan := make(chan schemaProxyBuildResult)
|
propNamesChan := make(chan schemaProxyBuildResult)
|
||||||
unevalItemsChan := make(chan schemaProxyBuildResult)
|
unevalItemsChan := make(chan schemaProxyBuildResult)
|
||||||
unevalPropsChan := make(chan schemaProxyBuildResult)
|
unevalPropsChan := make(chan schemaProxyBuildResult)
|
||||||
|
addPropsChan := make(chan schemaProxyBuildResult)
|
||||||
|
|
||||||
totalBuilds := countSubSchemaItems(allOfValue) +
|
totalBuilds := countSubSchemaItems(allOfValue) +
|
||||||
countSubSchemaItems(anyOfValue) +
|
countSubSchemaItems(anyOfValue) +
|
||||||
@@ -875,52 +828,56 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
countSubSchemaItems(prefixItemsValue)
|
countSubSchemaItems(prefixItemsValue)
|
||||||
|
|
||||||
if allOfValue != nil {
|
if allOfValue != nil {
|
||||||
go buildSchema(allOfChan, allOfLabel, allOfValue, errorChan, idx)
|
go buildSchema(ctx, allOfChan, allOfLabel, allOfValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if anyOfValue != nil {
|
if anyOfValue != nil {
|
||||||
go buildSchema(anyOfChan, anyOfLabel, anyOfValue, errorChan, idx)
|
go buildSchema(ctx, anyOfChan, anyOfLabel, anyOfValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if oneOfValue != nil {
|
if oneOfValue != nil {
|
||||||
go buildSchema(oneOfChan, oneOfLabel, oneOfValue, errorChan, idx)
|
go buildSchema(ctx, oneOfChan, oneOfLabel, oneOfValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if prefixItemsValue != nil {
|
if prefixItemsValue != nil {
|
||||||
go buildSchema(prefixItemsChan, prefixItemsLabel, prefixItemsValue, errorChan, idx)
|
go buildSchema(ctx, prefixItemsChan, prefixItemsLabel, prefixItemsValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if notValue != nil {
|
if notValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(notChan, notLabel, notValue, errorChan, idx)
|
go buildSchema(ctx, notChan, notLabel, notValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if containsValue != nil {
|
if containsValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(containsChan, containsLabel, containsValue, errorChan, idx)
|
go buildSchema(ctx, containsChan, containsLabel, containsValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if !itemsIsBool && itemsValue != nil {
|
if !itemsIsBool && itemsValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(itemsChan, itemsLabel, itemsValue, errorChan, idx)
|
go buildSchema(ctx, itemsChan, itemsLabel, itemsValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if sifValue != nil {
|
if sifValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(ifChan, sifLabel, sifValue, errorChan, idx)
|
go buildSchema(ctx, ifChan, sifLabel, sifValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if selseValue != nil {
|
if selseValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(elseChan, selseLabel, selseValue, errorChan, idx)
|
go buildSchema(ctx, elseChan, selseLabel, selseValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if sthenValue != nil {
|
if sthenValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(thenChan, sthenLabel, sthenValue, errorChan, idx)
|
go buildSchema(ctx, thenChan, sthenLabel, sthenValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if propNamesValue != nil {
|
if propNamesValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(propNamesChan, propNamesLabel, propNamesValue, errorChan, idx)
|
go buildSchema(ctx, propNamesChan, propNamesLabel, propNamesValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if unevalItemsValue != nil {
|
if unevalItemsValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(unevalItemsChan, unevalItemsLabel, unevalItemsValue, errorChan, idx)
|
go buildSchema(ctx, unevalItemsChan, unevalItemsLabel, unevalItemsValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
if !unevalIsBool && unevalPropsValue != nil {
|
if !unevalIsBool && unevalPropsValue != nil {
|
||||||
totalBuilds++
|
totalBuilds++
|
||||||
go buildSchema(unevalPropsChan, unevalPropsLabel, unevalPropsValue, errorChan, idx)
|
go buildSchema(ctx, unevalPropsChan, unevalPropsLabel, unevalPropsValue, errorChan, idx)
|
||||||
|
}
|
||||||
|
if !addPropsIsBool && addPropsValue != nil {
|
||||||
|
totalBuilds++
|
||||||
|
go buildSchema(ctx, addPropsChan, addPropsLabel, addPropsValue, errorChan, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
completeCount := 0
|
completeCount := 0
|
||||||
@@ -967,6 +924,9 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
case r := <-unevalPropsChan:
|
case r := <-unevalPropsChan:
|
||||||
completeCount++
|
completeCount++
|
||||||
unevalProperties = r.v
|
unevalProperties = r.v
|
||||||
|
case r := <-addPropsChan:
|
||||||
|
completeCount++
|
||||||
|
addProperties = r.v
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1057,22 +1017,31 @@ func (s *Schema) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !unevalIsBool && !unevalProperties.IsEmpty() {
|
if !unevalIsBool && !unevalProperties.IsEmpty() {
|
||||||
s.UnevaluatedProperties = low.NodeReference[*SchemaDynamicValue[*SchemaProxy, *bool]]{
|
s.UnevaluatedProperties = low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]{
|
||||||
Value: &SchemaDynamicValue[*SchemaProxy, *bool]{
|
Value: &SchemaDynamicValue[*SchemaProxy, bool]{
|
||||||
A: unevalProperties.Value,
|
A: unevalProperties.Value,
|
||||||
},
|
},
|
||||||
KeyNode: unevalPropsLabel,
|
KeyNode: unevalPropsLabel,
|
||||||
ValueNode: unevalPropsValue,
|
ValueNode: unevalPropsValue,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !addPropsIsBool && !addProperties.IsEmpty() {
|
||||||
|
s.AdditionalProperties = low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]{
|
||||||
|
Value: &SchemaDynamicValue[*SchemaProxy, bool]{
|
||||||
|
A: addProperties.Value,
|
||||||
|
},
|
||||||
|
KeyNode: addPropsLabel,
|
||||||
|
ValueNode: addPropsValue,
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]], error) {
|
func buildPropertyMap(ctx context.Context, root *yaml.Node, idx *index.SpecIndex, label string) (*low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]], error) {
|
||||||
// for property, build in a new thread!
|
// for property, build in a new thread!
|
||||||
bChan := make(chan schemaProxyBuildResult)
|
bChan := make(chan schemaProxyBuildResult)
|
||||||
|
|
||||||
buildProperty := func(label *yaml.Node, value *yaml.Node, c chan schemaProxyBuildResult, isRef bool,
|
buildProperty := func(ctx context.Context, label *yaml.Node, value *yaml.Node, c chan schemaProxyBuildResult, isRef bool,
|
||||||
refString string,
|
refString string,
|
||||||
) {
|
) {
|
||||||
c <- schemaProxyBuildResult{
|
c <- schemaProxyBuildResult{
|
||||||
@@ -1081,7 +1050,7 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
Value: label.Value,
|
Value: label.Value,
|
||||||
},
|
},
|
||||||
v: low.ValueReference[*SchemaProxy]{
|
v: low.ValueReference[*SchemaProxy]{
|
||||||
Value: &SchemaProxy{kn: label, vn: value, idx: idx, isReference: isRef, referenceLookup: refString},
|
Value: &SchemaProxy{ctx: ctx, kn: label, vn: value, idx: idx, isReference: isRef, referenceLookup: refString},
|
||||||
ValueNode: value,
|
ValueNode: value,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -1098,22 +1067,24 @@ func buildPropertyMap(root *yaml.Node, idx *index.SpecIndex, label string) (*low
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foundCtx := ctx
|
||||||
// check our prop isn't reference
|
// check our prop isn't reference
|
||||||
isRef := false
|
isRef := false
|
||||||
refString := ""
|
refString := ""
|
||||||
if h, _, l := utils.IsNodeRefValue(prop); h {
|
if h, _, l := utils.IsNodeRefValue(prop); h {
|
||||||
ref, _ := low.LocateRefNode(prop, idx)
|
ref, _, _, fctx := low.LocateRefNodeWithContext(ctx, prop, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
isRef = true
|
isRef = true
|
||||||
prop = ref
|
prop = ref
|
||||||
refString = l
|
refString = l
|
||||||
|
foundCtx = fctx
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("schema properties build failed: cannot find reference %s, line %d, col %d",
|
return nil, fmt.Errorf("schema properties build failed: cannot find reference %s, line %d, col %d",
|
||||||
prop.Content[1].Value, prop.Content[1].Line, prop.Content[1].Column)
|
prop.Content[1].Value, prop.Content[1].Line, prop.Content[1].Column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalProps++
|
totalProps++
|
||||||
go buildProperty(currentProp, prop, bChan, isRef, refString)
|
go buildProperty(foundCtx, currentProp, prop, bChan, isRef, refString)
|
||||||
}
|
}
|
||||||
completedProps := 0
|
completedProps := 0
|
||||||
for completedProps < totalProps {
|
for completedProps < totalProps {
|
||||||
@@ -1155,7 +1126,7 @@ func (s *Schema) extractExtensions(root *yaml.Node) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// build out a child schema for parent schema.
|
// build out a child schema for parent schema.
|
||||||
func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml.Node, errors chan error, idx *index.SpecIndex) {
|
func buildSchema(ctx context.Context, schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml.Node, errors chan error, idx *index.SpecIndex) {
|
||||||
if valueNode != nil {
|
if valueNode != nil {
|
||||||
type buildResult struct {
|
type buildResult struct {
|
||||||
res *low.ValueReference[*SchemaProxy]
|
res *low.ValueReference[*SchemaProxy]
|
||||||
@@ -1165,7 +1136,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
syncChan := make(chan buildResult)
|
syncChan := make(chan buildResult)
|
||||||
|
|
||||||
// build out a SchemaProxy for every sub-schema.
|
// build out a SchemaProxy for every sub-schema.
|
||||||
build := func(kn *yaml.Node, vn *yaml.Node, schemaIdx int, c chan buildResult,
|
build := func(pctx context.Context, kn *yaml.Node, vn *yaml.Node, schemaIdx int, c chan buildResult,
|
||||||
isRef bool, refLocation string,
|
isRef bool, refLocation string,
|
||||||
) {
|
) {
|
||||||
// a proxy design works best here. polymorphism, pretty much guarantees that a sub-schema can
|
// a proxy design works best here. polymorphism, pretty much guarantees that a sub-schema can
|
||||||
@@ -1178,6 +1149,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
sp.kn = kn
|
sp.kn = kn
|
||||||
sp.vn = vn
|
sp.vn = vn
|
||||||
sp.idx = idx
|
sp.idx = idx
|
||||||
|
sp.ctx = pctx
|
||||||
if isRef {
|
if isRef {
|
||||||
sp.referenceLookup = refLocation
|
sp.referenceLookup = refLocation
|
||||||
sp.isReference = true
|
sp.isReference = true
|
||||||
@@ -1194,13 +1166,15 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
|
|
||||||
isRef := false
|
isRef := false
|
||||||
refLocation := ""
|
refLocation := ""
|
||||||
|
foundCtx := ctx
|
||||||
if utils.IsNodeMap(valueNode) {
|
if utils.IsNodeMap(valueNode) {
|
||||||
h := false
|
h := false
|
||||||
if h, _, refLocation = utils.IsNodeRefValue(valueNode); h {
|
if h, _, refLocation = utils.IsNodeRefValue(valueNode); h {
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(valueNode, idx)
|
ref, _, _, fctx := low.LocateRefNodeWithContext(ctx, valueNode, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
valueNode = ref
|
valueNode = ref
|
||||||
|
foundCtx = fctx
|
||||||
} else {
|
} else {
|
||||||
errors <- fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
errors <- fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
||||||
valueNode.Content[1].Value, valueNode.Content[1].Line, valueNode.Content[1].Column)
|
valueNode.Content[1].Value, valueNode.Content[1].Line, valueNode.Content[1].Column)
|
||||||
@@ -1209,7 +1183,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
|
|
||||||
// this only runs once, however to keep things consistent, it makes sense to use the same async method
|
// this only runs once, however to keep things consistent, it makes sense to use the same async method
|
||||||
// that arrays will use.
|
// that arrays will use.
|
||||||
go build(labelNode, valueNode, -1, syncChan, isRef, refLocation)
|
go build(foundCtx, labelNode, valueNode, -1, syncChan, isRef, refLocation)
|
||||||
select {
|
select {
|
||||||
case r := <-syncChan:
|
case r := <-syncChan:
|
||||||
schemas <- schemaProxyBuildResult{
|
schemas <- schemaProxyBuildResult{
|
||||||
@@ -1220,8 +1194,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
v: *r.res,
|
v: *r.res,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else if utils.IsNodeArray(valueNode) {
|
||||||
if utils.IsNodeArray(valueNode) {
|
|
||||||
refBuilds := 0
|
refBuilds := 0
|
||||||
results := make([]*low.ValueReference[*SchemaProxy], len(valueNode.Content))
|
results := make([]*low.ValueReference[*SchemaProxy], len(valueNode.Content))
|
||||||
|
|
||||||
@@ -1230,9 +1203,10 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
h := false
|
h := false
|
||||||
if h, _, refLocation = utils.IsNodeRefValue(vn); h {
|
if h, _, refLocation = utils.IsNodeRefValue(vn); h {
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(vn, idx)
|
ref, _, _, fctx := low.LocateRefNodeWithContext(ctx, vn, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
vn = ref
|
vn = ref
|
||||||
|
foundCtx = fctx
|
||||||
} else {
|
} else {
|
||||||
err := fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
err := fmt.Errorf("build schema failed: reference cannot be found: %s, line %d, col %d",
|
||||||
vn.Content[1].Value, vn.Content[1].Line, vn.Content[1].Column)
|
vn.Content[1].Value, vn.Content[1].Line, vn.Content[1].Column)
|
||||||
@@ -1241,7 +1215,7 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
refBuilds++
|
refBuilds++
|
||||||
go build(vn, vn, i, syncChan, isRef, refLocation)
|
go build(foundCtx, vn, vn, i, syncChan, isRef, refLocation)
|
||||||
}
|
}
|
||||||
|
|
||||||
completedBuilds := 0
|
completedBuilds := 0
|
||||||
@@ -1262,6 +1236,8 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
v: *r,
|
v: *r,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
errors <- fmt.Errorf("build schema failed: unexpected node type: %s, line %d, col %d", valueNode.Tag, valueNode.Line, valueNode.Column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1269,22 +1245,29 @@ func buildSchema(schemas chan schemaProxyBuildResult, labelNode, valueNode *yaml
|
|||||||
// ExtractSchema will return a pointer to a NodeReference that contains a *SchemaProxy if successful. The function
|
// ExtractSchema will return a pointer to a NodeReference that contains a *SchemaProxy if successful. The function
|
||||||
// will specifically look for a key node named 'schema' and extract the value mapped to that key. If the operation
|
// will specifically look for a key node named 'schema' and extract the value mapped to that key. If the operation
|
||||||
// fails then no NodeReference is returned and an error is returned instead.
|
// fails then no NodeReference is returned and an error is returned instead.
|
||||||
func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*SchemaProxy], error) {
|
func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*SchemaProxy], error) {
|
||||||
var schLabel, schNode *yaml.Node
|
var schLabel, schNode *yaml.Node
|
||||||
errStr := "schema build failed: reference '%s' cannot be found at line %d, col %d"
|
errStr := "schema build failed: reference '%s' cannot be found at line %d, col %d"
|
||||||
|
|
||||||
isRef := false
|
isRef := false
|
||||||
refLocation := ""
|
refLocation := ""
|
||||||
|
|
||||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||||
// locate reference in index.
|
// locate reference in index.
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(root, idx)
|
ref, fIdx, _, nCtx := low.LocateRefNodeWithContext(ctx, root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
schNode = ref
|
schNode = ref
|
||||||
schLabel = rl
|
schLabel = rl
|
||||||
|
ctx = nCtx
|
||||||
|
idx = fIdx
|
||||||
} else {
|
} else {
|
||||||
|
v := root.Content[1].Value
|
||||||
|
if root.Content[1].Value == "" {
|
||||||
|
v = "[empty]"
|
||||||
|
}
|
||||||
return nil, fmt.Errorf(errStr,
|
return nil, fmt.Errorf(errStr,
|
||||||
root.Content[1].Value, root.Content[1].Line, root.Content[1].Column)
|
v, root.Content[1].Line, root.Content[1].Column)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, schLabel, schNode = utils.FindKeyNodeFull(SchemaLabel, root.Content)
|
_, schLabel, schNode = utils.FindKeyNodeFull(SchemaLabel, root.Content)
|
||||||
@@ -1292,12 +1275,21 @@ func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*S
|
|||||||
h := false
|
h := false
|
||||||
if h, _, refLocation = utils.IsNodeRefValue(schNode); h {
|
if h, _, refLocation = utils.IsNodeRefValue(schNode); h {
|
||||||
isRef = true
|
isRef = true
|
||||||
ref, _ := low.LocateRefNode(schNode, idx)
|
ref, foundIdx, _, nCtx := low.LocateRefNodeWithContext(ctx, schNode, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
schNode = ref
|
schNode = ref
|
||||||
|
if foundIdx != nil {
|
||||||
|
// TODO: check on this
|
||||||
|
//idx = foundIdx
|
||||||
|
}
|
||||||
|
ctx = nCtx
|
||||||
} else {
|
} else {
|
||||||
|
v := schNode.Content[1].Value
|
||||||
|
if schNode.Content[1].Value == "" {
|
||||||
|
v = "[empty]"
|
||||||
|
}
|
||||||
return nil, fmt.Errorf(errStr,
|
return nil, fmt.Errorf(errStr,
|
||||||
schNode.Content[1].Value, schNode.Content[1].Line, schNode.Content[1].Column)
|
v, schNode.Content[1].Line, schNode.Content[1].Column)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1305,7 +1297,7 @@ func ExtractSchema(root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*S
|
|||||||
|
|
||||||
if schNode != nil {
|
if schNode != nil {
|
||||||
// check if schema has already been built.
|
// check if schema has already been built.
|
||||||
schema := &SchemaProxy{kn: schLabel, vn: schNode, idx: idx, isReference: isRef, referenceLookup: refLocation}
|
schema := &SchemaProxy{kn: schLabel, vn: schNode, idx: idx, ctx: ctx, isReference: isRef, referenceLookup: refLocation}
|
||||||
return &low.NodeReference[*SchemaProxy]{
|
return &low.NodeReference[*SchemaProxy]{
|
||||||
Value: schema, KeyNode: schLabel, ValueNode: schNode, ReferenceNode: isRef,
|
Value: schema, KeyNode: schLabel, ValueNode: schNode, ReferenceNode: isRef,
|
||||||
Reference: refLocation,
|
Reference: refLocation,
|
||||||
|
|||||||
@@ -4,8 +4,8 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
@@ -51,14 +51,16 @@ type SchemaProxy struct {
|
|||||||
buildError error
|
buildError error
|
||||||
isReference bool // Is the schema underneath originally a $ref?
|
isReference bool // Is the schema underneath originally a $ref?
|
||||||
referenceLookup string // If the schema is a $ref, what's its name?
|
referenceLookup string // If the schema is a $ref, what's its name?
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build will prepare the SchemaProxy for rendering, it does not build the Schema, only sets up internal state.
|
// Build will prepare the SchemaProxy for rendering, it does not build the Schema, only sets up internal state.
|
||||||
// Key maybe nil if absent.
|
// Key maybe nil if absent.
|
||||||
func (sp *SchemaProxy) Build(key, value *yaml.Node, idx *index.SpecIndex) error {
|
func (sp *SchemaProxy) Build(ctx context.Context, key, value *yaml.Node, idx *index.SpecIndex) error {
|
||||||
sp.kn = key
|
sp.kn = key
|
||||||
sp.vn = value
|
sp.vn = value
|
||||||
sp.idx = idx
|
sp.idx = idx
|
||||||
|
sp.ctx = ctx
|
||||||
if rf, _, r := utils.IsNodeRefValue(value); rf {
|
if rf, _, r := utils.IsNodeRefValue(value); rf {
|
||||||
sp.isReference = true
|
sp.isReference = true
|
||||||
sp.referenceLookup = r
|
sp.referenceLookup = r
|
||||||
@@ -83,7 +85,7 @@ func (sp *SchemaProxy) Schema() *Schema {
|
|||||||
}
|
}
|
||||||
schema := new(Schema)
|
schema := new(Schema)
|
||||||
utils.CheckForMergeNodes(sp.vn)
|
utils.CheckForMergeNodes(sp.vn)
|
||||||
err := schema.Build(sp.vn, sp.idx)
|
err := schema.Build(sp.ctx, sp.vn, sp.idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
sp.buildError = err
|
sp.buildError = err
|
||||||
return nil
|
return nil
|
||||||
@@ -129,6 +131,20 @@ func (sp *SchemaProxy) GetSchemaReference() string {
|
|||||||
return sp.referenceLookup
|
return sp.referenceLookup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (sp *SchemaProxy) GetSchemaReferenceLocation() *index.NodeOrigin {
|
||||||
|
if sp.idx != nil {
|
||||||
|
origin := sp.idx.FindNodeOrigin(sp.vn)
|
||||||
|
if origin != nil {
|
||||||
|
return origin
|
||||||
|
}
|
||||||
|
if sp.idx.GetRolodex() != nil {
|
||||||
|
origin = sp.idx.GetRolodex().FindNodeOrigin(sp.vn)
|
||||||
|
return origin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// GetKeyNode will return the yaml.Node pointer that is a key for value node.
|
// GetKeyNode will return the yaml.Node pointer that is a key for value node.
|
||||||
func (sp *SchemaProxy) GetKeyNode() *yaml.Node {
|
func (sp *SchemaProxy) GetKeyNode() *yaml.Node {
|
||||||
return sp.kn
|
return sp.kn
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -19,7 +21,7 @@ description: something`
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
err := sch.Build(&idxNode, idxNode.Content[0], nil)
|
err := sch.Build(context.Background(), &idxNode, idxNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "db2a35dd6fb3d9481d0682571b9d687616bb2a34c1887f7863f0b2e769ca7b23",
|
assert.Equal(t, "db2a35dd6fb3d9481d0682571b9d687616bb2a34c1887f7863f0b2e769ca7b23",
|
||||||
@@ -51,7 +53,7 @@ func TestSchemaProxy_Build_CheckRef(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
err := sch.Build(nil, idxNode.Content[0], nil)
|
err := sch.Build(context.Background(), nil, idxNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, sch.IsSchemaReference())
|
assert.True(t, sch.IsSchemaReference())
|
||||||
assert.Equal(t, "wat", sch.GetSchemaReference())
|
assert.Equal(t, "wat", sch.GetSchemaReference())
|
||||||
@@ -67,7 +69,7 @@ func TestSchemaProxy_Build_HashInline(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
err := sch.Build(nil, idxNode.Content[0], nil)
|
err := sch.Build(context.Background(), nil, idxNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.False(t, sch.IsSchemaReference())
|
assert.False(t, sch.IsSchemaReference())
|
||||||
assert.NotNil(t, sch.Schema())
|
assert.NotNil(t, sch.Schema())
|
||||||
@@ -89,9 +91,73 @@ x-common-definitions:
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
err := sch.Build(nil, idxNode.Content[0], nil)
|
err := sch.Build(context.Background(), nil, idxNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Len(t, sch.Schema().Enum.Value, 3)
|
assert.Len(t, sch.Schema().Enum.Value, 3)
|
||||||
assert.Equal(t, "The type of life cycle", sch.Schema().Description.Value)
|
assert.Equal(t, "The type of life cycle", sch.Schema().Description.Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSchemaProxy_GetSchemaReferenceLocation(t *testing.T) {
|
||||||
|
|
||||||
|
yml := `type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: thing`
|
||||||
|
|
||||||
|
var idxNodeA yaml.Node
|
||||||
|
e := yaml.Unmarshal([]byte(yml), &idxNodeA)
|
||||||
|
assert.NoError(t, e)
|
||||||
|
|
||||||
|
yml = `
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
description: thang`
|
||||||
|
|
||||||
|
var schA SchemaProxy
|
||||||
|
var schB SchemaProxy
|
||||||
|
var schC SchemaProxy
|
||||||
|
var idxNodeB yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNodeB)
|
||||||
|
|
||||||
|
c := index.CreateOpenAPIIndexConfig()
|
||||||
|
rolo := index.NewRolodex(c)
|
||||||
|
rolo.SetRootNode(&idxNodeA)
|
||||||
|
_ = rolo.IndexTheRolodex()
|
||||||
|
|
||||||
|
err := schA.Build(context.Background(), nil, idxNodeA.Content[0], rolo.GetRootIndex())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
err = schB.Build(context.Background(), nil, idxNodeB.Content[0].Content[3].Content[1], rolo.GetRootIndex())
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
rolo.GetRootIndex().SetAbsolutePath("/rooty/rootster")
|
||||||
|
origin := schA.GetSchemaReferenceLocation()
|
||||||
|
assert.NotNil(t, origin)
|
||||||
|
assert.Equal(t, "/rooty/rootster", origin.AbsoluteLocation)
|
||||||
|
|
||||||
|
// mess things up so it cannot be found
|
||||||
|
schA.vn = schB.vn
|
||||||
|
origin = schA.GetSchemaReferenceLocation()
|
||||||
|
assert.Nil(t, origin)
|
||||||
|
|
||||||
|
// create a new index
|
||||||
|
idx := index.NewSpecIndexWithConfig(&idxNodeB, c)
|
||||||
|
idx.SetAbsolutePath("/boaty/mcboatface")
|
||||||
|
|
||||||
|
// add the index to the rolodex
|
||||||
|
rolo.AddIndex(idx)
|
||||||
|
|
||||||
|
// can now find the origin
|
||||||
|
origin = schA.GetSchemaReferenceLocation()
|
||||||
|
assert.NotNil(t, origin)
|
||||||
|
assert.Equal(t, "/boaty/mcboatface", origin.AbsoluteLocation)
|
||||||
|
|
||||||
|
// do it again, but with no index
|
||||||
|
err = schC.Build(context.Background(), nil, idxNodeA.Content[0], nil)
|
||||||
|
origin = schC.GetSchemaReferenceLocation()
|
||||||
|
assert.Nil(t, origin)
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"context"
|
||||||
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/orderedmap"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/resolver"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func test_get_schema_blob() string {
|
func test_get_schema_blob() string {
|
||||||
@@ -167,10 +167,10 @@ func Test_Schema(t *testing.T) {
|
|||||||
mbErr := low.BuildModel(rootNode.Content[0], &sch)
|
mbErr := low.BuildModel(rootNode.Content[0], &sch)
|
||||||
assert.NoError(t, mbErr)
|
assert.NoError(t, mbErr)
|
||||||
|
|
||||||
schErr := sch.Build(rootNode.Content[0], nil)
|
schErr := sch.Build(context.Background(), rootNode.Content[0], nil)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
assert.Equal(t, "something object", sch.Description.Value)
|
assert.Equal(t, "something object", sch.Description.Value)
|
||||||
assert.True(t, sch.AdditionalProperties.Value.(bool))
|
assert.True(t, sch.AdditionalProperties.Value.B)
|
||||||
|
|
||||||
assert.Equal(t, 2, orderedmap.Len(sch.Properties.Value))
|
assert.Equal(t, 2, orderedmap.Len(sch.Properties.Value))
|
||||||
v := sch.FindProperty("somethingB")
|
v := sch.FindProperty("somethingB")
|
||||||
@@ -343,7 +343,7 @@ func TestSchemaAllOfSequenceOrder(t *testing.T) {
|
|||||||
mbErr := low.BuildModel(rootNode.Content[0], &sch)
|
mbErr := low.BuildModel(rootNode.Content[0], &sch)
|
||||||
assert.NoError(t, mbErr)
|
assert.NoError(t, mbErr)
|
||||||
|
|
||||||
schErr := sch.Build(rootNode.Content[0], nil)
|
schErr := sch.Build(context.Background(), rootNode.Content[0], nil)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
assert.Equal(t, "allOf sequence check", sch.Description.Value)
|
assert.Equal(t, "allOf sequence check", sch.Description.Value)
|
||||||
|
|
||||||
@@ -363,13 +363,13 @@ func TestSchema_Hash(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &sc1n)
|
_ = yaml.Unmarshal([]byte(testSpec), &sc1n)
|
||||||
sch1 := Schema{}
|
sch1 := Schema{}
|
||||||
_ = low.BuildModel(&sc1n, &sch1)
|
_ = low.BuildModel(&sc1n, &sch1)
|
||||||
_ = sch1.Build(sc1n.Content[0], nil)
|
_ = sch1.Build(context.Background(), sc1n.Content[0], nil)
|
||||||
|
|
||||||
var sc2n yaml.Node
|
var sc2n yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(testSpec), &sc2n)
|
_ = yaml.Unmarshal([]byte(testSpec), &sc2n)
|
||||||
sch2 := Schema{}
|
sch2 := Schema{}
|
||||||
_ = low.BuildModel(&sc2n, &sch2)
|
_ = low.BuildModel(&sc2n, &sch2)
|
||||||
_ = sch2.Build(sc2n.Content[0], nil)
|
_ = sch2.Build(context.Background(), sc2n.Content[0], nil)
|
||||||
|
|
||||||
assert.Equal(t, sch1.Hash(), sch2.Hash())
|
assert.Equal(t, sch1.Hash(), sch2.Hash())
|
||||||
}
|
}
|
||||||
@@ -381,13 +381,13 @@ func BenchmarkSchema_Hash(b *testing.B) {
|
|||||||
_ = yaml.Unmarshal([]byte(testSpec), &sc1n)
|
_ = yaml.Unmarshal([]byte(testSpec), &sc1n)
|
||||||
sch1 := Schema{}
|
sch1 := Schema{}
|
||||||
_ = low.BuildModel(&sc1n, &sch1)
|
_ = low.BuildModel(&sc1n, &sch1)
|
||||||
_ = sch1.Build(sc1n.Content[0], nil)
|
_ = sch1.Build(context.Background(), sc1n.Content[0], nil)
|
||||||
|
|
||||||
var sc2n yaml.Node
|
var sc2n yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(testSpec), &sc2n)
|
_ = yaml.Unmarshal([]byte(testSpec), &sc2n)
|
||||||
sch2 := Schema{}
|
sch2 := Schema{}
|
||||||
_ = low.BuildModel(&sc2n, &sch2)
|
_ = low.BuildModel(&sc2n, &sch2)
|
||||||
_ = sch2.Build(sc2n.Content[0], nil)
|
_ = sch2.Build(context.Background(), sc2n.Content[0], nil)
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
assert.Equal(b, sch1.Hash(), sch2.Hash())
|
assert.Equal(b, sch1.Hash(), sch2.Hash())
|
||||||
@@ -417,7 +417,7 @@ const: tasty`
|
|||||||
mbErr := low.BuildModel(rootNode.Content[0], &sch)
|
mbErr := low.BuildModel(rootNode.Content[0], &sch)
|
||||||
assert.NoError(t, mbErr)
|
assert.NoError(t, mbErr)
|
||||||
|
|
||||||
schErr := sch.Build(rootNode.Content[0], nil)
|
schErr := sch.Build(context.Background(), rootNode.Content[0], nil)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
assert.Equal(t, "something object", sch.Description.Value)
|
assert.Equal(t, "something object", sch.Description.Value)
|
||||||
assert.Len(t, sch.Type.Value.B, 2)
|
assert.Len(t, sch.Type.Value.B, 2)
|
||||||
@@ -458,7 +458,7 @@ properties:
|
|||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
var n Schema
|
var n Schema
|
||||||
err := n.Build(idxNode.Content[0], idx)
|
err := n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "this is something", n.FindProperty("aValue").Value.Schema().Description.Value)
|
assert.Equal(t, "this is something", n.FindProperty("aValue").Value.Schema().Description.Value)
|
||||||
}
|
}
|
||||||
@@ -484,7 +484,7 @@ properties:
|
|||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
var n Schema
|
var n Schema
|
||||||
err := n.Build(idxNode.Content[0], idx)
|
err := n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -509,7 +509,7 @@ dependentSchemas:
|
|||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
var n Schema
|
var n Schema
|
||||||
err := n.Build(idxNode.Content[0], idx)
|
err := n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,7 +534,7 @@ patternProperties:
|
|||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
var n Schema
|
var n Schema
|
||||||
err := n.Build(idxNode.Content[0], idx)
|
err := n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -574,7 +574,7 @@ items:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
|
|
||||||
desc := "poly thing"
|
desc := "poly thing"
|
||||||
@@ -621,7 +621,7 @@ items:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, schErr)
|
assert.Error(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -661,7 +661,7 @@ items:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
|
|
||||||
desc := "poly thing"
|
desc := "poly thing"
|
||||||
@@ -708,7 +708,7 @@ items:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, schErr)
|
assert.Error(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,7 +734,7 @@ allOf:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, schErr)
|
assert.Error(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -760,7 +760,7 @@ allOf:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, schErr)
|
assert.Error(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -788,7 +788,7 @@ allOf:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
assert.Nil(t, sch.AllOf.Value[0].Value.Schema()) // child can't be resolved, so this will be nil.
|
assert.Nil(t, sch.AllOf.Value[0].Value.Schema()) // child can't be resolved, so this will be nil.
|
||||||
assert.Error(t, sch.AllOf.Value[0].Value.GetBuildError())
|
assert.Error(t, sch.AllOf.Value[0].Value.GetBuildError())
|
||||||
@@ -818,7 +818,7 @@ allOf:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
|
|
||||||
desc := "madness"
|
desc := "madness"
|
||||||
@@ -849,7 +849,7 @@ allOf:
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = sch.Build(idxNode.Content[0], idx)
|
err = sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -877,7 +877,7 @@ func Test_Schema_Polymorphism_RefMadnessIllegal(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, schErr)
|
assert.NoError(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -902,14 +902,14 @@ func Test_Schema_RefMadnessIllegal_Circular(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, schErr)
|
assert.Error(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -934,14 +934,14 @@ func Test_Schema_RefMadnessIllegal_Nonexist(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
err := low.BuildModel(&idxNode, &sch)
|
err := low.BuildModel(&idxNode, &sch)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
schErr := sch.Build(idxNode.Content[0], idx)
|
schErr := sch.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, schErr)
|
assert.Error(t, schErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -966,7 +966,7 @@ func TestExtractSchema(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res.Value)
|
assert.NotNil(t, res.Value)
|
||||||
aValue := res.Value.Schema().FindProperty("aValue")
|
aValue := res.Value.Schema().FindProperty("aValue")
|
||||||
@@ -982,7 +982,7 @@ schema:
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], nil)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res.Value)
|
assert.NotNil(t, res.Value)
|
||||||
sch := res.Value.Schema()
|
sch := res.Value.Schema()
|
||||||
@@ -998,7 +998,7 @@ schema:
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], nil)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res.Value)
|
assert.NotNil(t, res.Value)
|
||||||
sch := res.Value.Schema()
|
sch := res.Value.Schema()
|
||||||
@@ -1023,7 +1023,7 @@ func TestExtractSchema_Ref(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res.Value)
|
assert.NotNil(t, res.Value)
|
||||||
assert.Equal(t, "this is something", res.Value.Schema().Description.Value)
|
assert.Equal(t, "this is something", res.Value.Schema().Description.Value)
|
||||||
@@ -1047,7 +1047,7 @@ func TestExtractSchema_Ref_Fail(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
_, err := ExtractSchema(idxNode.Content[0], idx)
|
_, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1075,14 +1075,14 @@ func TestExtractSchema_CheckChildPropCircular(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Something'`
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res.Value)
|
assert.NotNil(t, res.Value)
|
||||||
|
|
||||||
@@ -1107,7 +1107,7 @@ func TestExtractSchema_RefRoot(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotNil(t, res.Value)
|
assert.NotNil(t, res.Value)
|
||||||
assert.Equal(t, "this is something", res.Value.Schema().Description.Value)
|
assert.Equal(t, "this is something", res.Value.Schema().Description.Value)
|
||||||
@@ -1130,7 +1130,7 @@ func TestExtractSchema_RefRoot_Fail(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
_, err := ExtractSchema(idxNode.Content[0], idx)
|
_, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1150,7 +1150,7 @@ func TestExtractSchema_RefRoot_Child_Fail(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
_, err := ExtractSchema(idxNode.Content[0], idx)
|
_, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1171,32 +1171,9 @@ func TestExtractSchema_AdditionalPropertiesAsSchema(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.NotNil(t, res.Value.Schema().AdditionalProperties.Value.(*SchemaProxy).Schema())
|
assert.NotNil(t, res.Value.Schema().AdditionalProperties.Value.A.Schema())
|
||||||
assert.Nil(t, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestExtractSchema_AdditionalPropertiesAsSchemaSlice(t *testing.T) {
|
|
||||||
yml := `components:
|
|
||||||
schemas:
|
|
||||||
Something:
|
|
||||||
additionalProperties:
|
|
||||||
- nice: rice`
|
|
||||||
|
|
||||||
var iNode yaml.Node
|
|
||||||
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
|
||||||
assert.NoError(t, mErr)
|
|
||||||
idx := index.NewSpecIndex(&iNode)
|
|
||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Something'`
|
|
||||||
|
|
||||||
var idxNode yaml.Node
|
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
|
||||||
|
|
||||||
assert.NotNil(t, res.Value.Schema().AdditionalProperties.Value.([]low.ValueReference[interface{}]))
|
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1216,7 +1193,7 @@ func TestExtractSchema_DoNothing(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Nil(t, res)
|
assert.Nil(t, res)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
@@ -1244,8 +1221,8 @@ func TestExtractSchema_AdditionalProperties_Ref(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NotNil(t, res.Value.Schema().AdditionalProperties.Value.(*SchemaProxy).Schema())
|
assert.NotNil(t, res.Value.Schema().AdditionalProperties.Value.A.Schema())
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1358,7 +1335,7 @@ func TestExtractSchema_OneOfRef(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, err := ExtractSchema(idxNode.Content[0], idx)
|
res, err := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "a frosty cold beverage can be coke or sprite",
|
assert.Equal(t, "a frosty cold beverage can be coke or sprite",
|
||||||
res.Value.Schema().OneOf.Value[0].Value.Schema().Description.Value)
|
res.Value.Schema().OneOf.Value[0].Value.Schema().Description.Value)
|
||||||
@@ -1379,7 +1356,7 @@ func TestSchema_Hash_Equal(t *testing.T) {
|
|||||||
uniqueItems: 1
|
uniqueItems: 1
|
||||||
maxProperties: 10
|
maxProperties: 10
|
||||||
minProperties: 1
|
minProperties: 1
|
||||||
additionalProperties: anything
|
additionalProperties: true
|
||||||
description: milky
|
description: milky
|
||||||
contentEncoding: rubber shoes
|
contentEncoding: rubber shoes
|
||||||
contentMediaType: paper tiger
|
contentMediaType: paper tiger
|
||||||
@@ -1421,7 +1398,7 @@ func TestSchema_Hash_Equal(t *testing.T) {
|
|||||||
uniqueItems: 1
|
uniqueItems: 1
|
||||||
maxProperties: 10
|
maxProperties: 10
|
||||||
minProperties: 1
|
minProperties: 1
|
||||||
additionalProperties: anything
|
additionalProperties: true
|
||||||
description: milky
|
description: milky
|
||||||
contentEncoding: rubber shoes
|
contentEncoding: rubber shoes
|
||||||
contentMediaType: paper tiger
|
contentMediaType: paper tiger
|
||||||
@@ -1451,8 +1428,8 @@ func TestSchema_Hash_Equal(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||||
|
|
||||||
lDoc, _ := ExtractSchema(lNode.Content[0], nil)
|
lDoc, _ := ExtractSchema(context.Background(), lNode.Content[0], nil)
|
||||||
rDoc, _ := ExtractSchema(rNode.Content[0], nil)
|
rDoc, _ := ExtractSchema(context.Background(), rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.NotNil(t, lDoc)
|
assert.NotNil(t, lDoc)
|
||||||
assert.NotNil(t, rDoc)
|
assert.NotNil(t, rDoc)
|
||||||
@@ -1476,8 +1453,8 @@ func TestSchema_Hash_AdditionalPropsSlice(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||||
|
|
||||||
lDoc, _ := ExtractSchema(lNode.Content[0], nil)
|
lDoc, _ := ExtractSchema(context.Background(), lNode.Content[0], nil)
|
||||||
rDoc, _ := ExtractSchema(rNode.Content[0], nil)
|
rDoc, _ := ExtractSchema(context.Background(), rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.NotNil(t, lDoc)
|
assert.NotNil(t, lDoc)
|
||||||
assert.NotNil(t, rDoc)
|
assert.NotNil(t, rDoc)
|
||||||
@@ -1501,8 +1478,8 @@ func TestSchema_Hash_AdditionalPropsSliceNoMap(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||||
|
|
||||||
lDoc, _ := ExtractSchema(lNode.Content[0], nil)
|
lDoc, _ := ExtractSchema(context.Background(), lNode.Content[0], nil)
|
||||||
rDoc, _ := ExtractSchema(rNode.Content[0], nil)
|
rDoc, _ := ExtractSchema(context.Background(), rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.NotNil(t, lDoc)
|
assert.NotNil(t, lDoc)
|
||||||
assert.NotNil(t, rDoc)
|
assert.NotNil(t, rDoc)
|
||||||
@@ -1538,8 +1515,8 @@ func TestSchema_Hash_NotEqual(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||||
|
|
||||||
lDoc, _ := ExtractSchema(lNode.Content[0], nil)
|
lDoc, _ := ExtractSchema(context.Background(), lNode.Content[0], nil)
|
||||||
rDoc, _ := ExtractSchema(rNode.Content[0], nil)
|
rDoc, _ := ExtractSchema(context.Background(), rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.False(t, low.AreEqual(lDoc.Value.Schema(), rDoc.Value.Schema()))
|
assert.False(t, low.AreEqual(lDoc.Value.Schema(), rDoc.Value.Schema()))
|
||||||
}
|
}
|
||||||
@@ -1575,8 +1552,8 @@ func TestSchema_Hash_EqualJumbled(t *testing.T) {
|
|||||||
_ = yaml.Unmarshal([]byte(left), &lNode)
|
_ = yaml.Unmarshal([]byte(left), &lNode)
|
||||||
_ = yaml.Unmarshal([]byte(right), &rNode)
|
_ = yaml.Unmarshal([]byte(right), &rNode)
|
||||||
|
|
||||||
lDoc, _ := ExtractSchema(lNode.Content[0], nil)
|
lDoc, _ := ExtractSchema(context.Background(), lNode.Content[0], nil)
|
||||||
rDoc, _ := ExtractSchema(rNode.Content[0], nil)
|
rDoc, _ := ExtractSchema(context.Background(), rNode.Content[0], nil)
|
||||||
assert.True(t, low.AreEqual(lDoc.Value.Schema(), rDoc.Value.Schema()))
|
assert.True(t, low.AreEqual(lDoc.Value.Schema(), rDoc.Value.Schema()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1609,10 +1586,10 @@ func TestSchema_UnevaluatedPropertiesAsBool_DefinedAsTrue(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, _ := ExtractSchema(idxNode.Content[0], idx)
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.True(t, res.Value.Schema().UnevaluatedProperties.Value.IsB())
|
assert.True(t, res.Value.Schema().UnevaluatedProperties.Value.IsB())
|
||||||
assert.True(t, *res.Value.Schema().UnevaluatedProperties.Value.B)
|
assert.True(t, res.Value.Schema().UnevaluatedProperties.Value.B)
|
||||||
|
|
||||||
assert.Equal(t, "571bd1853c22393131e2dcadce86894da714ec14968895c8b7ed18154b2be8cd",
|
assert.Equal(t, "571bd1853c22393131e2dcadce86894da714ec14968895c8b7ed18154b2be8cd",
|
||||||
low.GenerateHashString(res.Value.Schema().UnevaluatedProperties.Value))
|
low.GenerateHashString(res.Value.Schema().UnevaluatedProperties.Value))
|
||||||
@@ -1634,10 +1611,10 @@ func TestSchema_UnevaluatedPropertiesAsBool_DefinedAsFalse(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, _ := ExtractSchema(idxNode.Content[0], idx)
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.True(t, res.Value.Schema().UnevaluatedProperties.Value.IsB())
|
assert.True(t, res.Value.Schema().UnevaluatedProperties.Value.IsB())
|
||||||
assert.False(t, *res.Value.Schema().UnevaluatedProperties.Value.B)
|
assert.False(t, res.Value.Schema().UnevaluatedProperties.Value.B)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSchema_UnevaluatedPropertiesAsBool_Undefined(t *testing.T) {
|
func TestSchema_UnevaluatedPropertiesAsBool_Undefined(t *testing.T) {
|
||||||
@@ -1656,7 +1633,186 @@ func TestSchema_UnevaluatedPropertiesAsBool_Undefined(t *testing.T) {
|
|||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
res, _ := ExtractSchema(idxNode.Content[0], idx)
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.Nil(t, res.Value.Schema().UnevaluatedProperties.Value)
|
assert.Nil(t, res.Value.Schema().UnevaluatedProperties.Value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestSchema_ExclusiveMinimum_3_with_Config(t *testing.T) {
|
||||||
|
yml := `openapi: 3.0.3
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Something:
|
||||||
|
type: integer
|
||||||
|
minimum: 3
|
||||||
|
exclusiveMinimum: true`
|
||||||
|
|
||||||
|
var iNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.0,
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := index.NewSpecIndexWithConfig(&iNode, config)
|
||||||
|
|
||||||
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
|
assert.True(t, res.Value.Schema().ExclusiveMinimum.Value.A)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_ExclusiveMinimum_31_with_Config(t *testing.T) {
|
||||||
|
yml := `openapi: 3.1
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Something:
|
||||||
|
type: integer
|
||||||
|
minimum: 3
|
||||||
|
exclusiveMinimum: 3`
|
||||||
|
|
||||||
|
var iNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.1,
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := index.NewSpecIndexWithConfig(&iNode, config)
|
||||||
|
|
||||||
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
|
assert.Equal(t, 3.0, res.Value.Schema().ExclusiveMinimum.Value.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_ExclusiveMaximum_3_with_Config(t *testing.T) {
|
||||||
|
yml := `openapi: 3.0.3
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Something:
|
||||||
|
type: integer
|
||||||
|
maximum: 3
|
||||||
|
exclusiveMaximum: true`
|
||||||
|
|
||||||
|
var iNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.0,
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := index.NewSpecIndexWithConfig(&iNode, config)
|
||||||
|
|
||||||
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
|
assert.True(t, res.Value.Schema().ExclusiveMaximum.Value.A)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_ExclusiveMaximum_31_with_Config(t *testing.T) {
|
||||||
|
yml := `openapi: 3.1
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Something:
|
||||||
|
type: integer
|
||||||
|
maximum: 3
|
||||||
|
exclusiveMaximum: 3`
|
||||||
|
|
||||||
|
var iNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.1,
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := index.NewSpecIndexWithConfig(&iNode, config)
|
||||||
|
|
||||||
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
|
res, _ := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
|
||||||
|
assert.Equal(t, 3.0, res.Value.Schema().ExclusiveMaximum.Value.B)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_EmptyySchemaRef(t *testing.T) {
|
||||||
|
yml := `openapi: 3.0.3
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Something:
|
||||||
|
$ref: ''`
|
||||||
|
|
||||||
|
var iNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.0,
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := index.NewSpecIndexWithConfig(&iNode, config)
|
||||||
|
|
||||||
|
yml = `schema:
|
||||||
|
$ref: ''`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
|
res, e := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
assert.Nil(t, res)
|
||||||
|
assert.Equal(t, "schema build failed: reference '[empty]' cannot be found at line 2, col 9", e.Error())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSchema_EmptyRef(t *testing.T) {
|
||||||
|
yml := `openapi: 3.0.3
|
||||||
|
components:
|
||||||
|
schemas:
|
||||||
|
Something:
|
||||||
|
$ref: ''`
|
||||||
|
|
||||||
|
var iNode yaml.Node
|
||||||
|
mErr := yaml.Unmarshal([]byte(yml), &iNode)
|
||||||
|
assert.NoError(t, mErr)
|
||||||
|
|
||||||
|
config := index.CreateOpenAPIIndexConfig()
|
||||||
|
config.SpecInfo = &datamodel.SpecInfo{
|
||||||
|
VersionNumeric: 3.0,
|
||||||
|
}
|
||||||
|
|
||||||
|
idx := index.NewSpecIndexWithConfig(&iNode, config)
|
||||||
|
|
||||||
|
yml = `$ref: ''`
|
||||||
|
|
||||||
|
var idxNode yaml.Node
|
||||||
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
|
res, e := ExtractSchema(context.Background(), idxNode.Content[0], idx)
|
||||||
|
assert.Nil(t, res)
|
||||||
|
assert.Equal(t, "schema build failed: reference '[empty]' cannot be found at line 1, col 7", e.Error())
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -30,7 +31,7 @@ type SecurityRequirement struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract security requirements from the node (the structure is odd, to be honest)
|
// Build will extract security requirements from the node (the structure is odd, to be honest)
|
||||||
func (s *SecurityRequirement) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
func (s *SecurityRequirement) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Reference = new(low.Reference)
|
s.Reference = new(low.Reference)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/orderedmap"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
@@ -35,8 +36,8 @@ one:
|
|||||||
var idxNode2 yaml.Node
|
var idxNode2 yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml2), &idxNode2)
|
_ = yaml.Unmarshal([]byte(yml2), &idxNode2)
|
||||||
|
|
||||||
_ = sr.Build(nil, idxNode.Content[0], nil)
|
_ = sr.Build(context.Background(), nil, idxNode.Content[0], nil)
|
||||||
_ = sr2.Build(nil, idxNode2.Content[0], nil)
|
_ = sr2.Build(context.Background(), nil, idxNode2.Content[0], nil)
|
||||||
|
|
||||||
assert.Equal(t, 2, orderedmap.Len(sr.Requirements.Value))
|
assert.Equal(t, 2, orderedmap.Len(sr.Requirements.Value))
|
||||||
assert.Len(t, sr.GetKeys(), 2)
|
assert.Len(t, sr.GetKeys(), 2)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -34,14 +35,14 @@ func (t *Tag) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and external docs for the Tag.
|
// Build will extract extensions and external docs for the Tag.
|
||||||
func (t *Tag) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (t *Tag) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
t.Reference = new(low.Reference)
|
t.Reference = new(low.Reference)
|
||||||
t.Extensions = low.ExtractExtensions(root)
|
t.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, err := low.ExtractObject[*ExternalDoc](ExternalDocsLabel, root, idx)
|
extDocs, err := low.ExtractObject[*ExternalDoc](ctx, ExternalDocsLabel, root, idx)
|
||||||
t.ExternalDocs = extDocs
|
t.ExternalDocs = extDocs
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -73,25 +74,3 @@ func (t *Tag) Hash() [32]byte {
|
|||||||
f = append(f, keys...)
|
f = append(f, keys...)
|
||||||
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
return sha256.Sum256([]byte(strings.Join(f, "|")))
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: future mutation API experiment code is here. this snippet is to re-marshal the object.
|
|
||||||
//func (t *Tag) MarshalYAML() (interface{}, error) {
|
|
||||||
// m := make(map[string]interface{})
|
|
||||||
// for i := range t.Extensions {
|
|
||||||
// m[i.Value] = t.Extensions[i].Value
|
|
||||||
// }
|
|
||||||
// if t.Name.Value != "" {
|
|
||||||
// m[NameLabel] = t.Name.Value
|
|
||||||
// }
|
|
||||||
// if t.Description.Value != "" {
|
|
||||||
// m[DescriptionLabel] = t.Description.Value
|
|
||||||
// }
|
|
||||||
// if t.ExternalDocs.Value != nil {
|
|
||||||
// m[ExternalDocsLabel] = t.ExternalDocs.Value
|
|
||||||
// }
|
|
||||||
// return m, nil
|
|
||||||
//}
|
|
||||||
//
|
|
||||||
//func NewTag() *Tag {
|
|
||||||
// return new(Tag)
|
|
||||||
//}
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package base
|
package base
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -27,7 +28,7 @@ x-coffee: tasty`
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "a tag", n.Name.Value)
|
assert.Equal(t, "a tag", n.Name.Value)
|
||||||
assert.Equal(t, "a description", n.Description.Value)
|
assert.Equal(t, "a description", n.Description.Value)
|
||||||
@@ -52,7 +53,7 @@ externalDocs:
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,8 +80,8 @@ x-b33f: princess`
|
|||||||
var rDoc Tag
|
var rDoc Tag
|
||||||
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
_ = low.BuildModel(lNode.Content[0], &lDoc)
|
||||||
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
_ = low.BuildModel(rNode.Content[0], &rDoc)
|
||||||
_ = lDoc.Build(nil, lNode.Content[0], nil)
|
_ = lDoc.Build(context.Background(), nil, lNode.Content[0], nil)
|
||||||
_ = rDoc.Build(nil, rNode.Content[0], nil)
|
_ = rDoc.Build(context.Background(), nil, rNode.Content[0], nil)
|
||||||
|
|
||||||
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
assert.Equal(t, lDoc.Hash(), rDoc.Hash())
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package low
|
package low
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
@@ -15,6 +16,8 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
|
"github.com/vmware-labs/yaml-jsonpath/pkg/yamlpath"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"net/url"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FindItemInMap accepts a string key and a collection of KeyReference[string] and ValueReference[T]. Every
|
// FindItemInMap accepts a string key and a collection of KeyReference[string] and ValueReference[T]. Every
|
||||||
@@ -64,26 +67,18 @@ func generateIndexCollection(idx *index.SpecIndex) []func() map[string]*index.Re
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// LocateRefNode will perform a complete lookup for a $ref node. This function searches the entire index for
|
func LocateRefNodeWithContext(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) (*yaml.Node, *index.SpecIndex, error, context.Context) {
|
||||||
// the reference being supplied. If there is a match found, the reference *yaml.Node is returned.
|
|
||||||
func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) (*yaml.Node, error) {
|
|
||||||
if rf, _, rv := utils.IsNodeRefValue(root); rf {
|
if rf, _, rv := utils.IsNodeRefValue(root); rf {
|
||||||
|
|
||||||
|
if rv == "" {
|
||||||
|
return nil, nil, fmt.Errorf("reference at line %d, column %d is empty, it cannot be resolved",
|
||||||
|
root.Line, root.Column), ctx
|
||||||
|
}
|
||||||
|
|
||||||
// run through everything and return as soon as we find a match.
|
// run through everything and return as soon as we find a match.
|
||||||
// this operates as fast as possible as ever
|
// this operates as fast as possible as ever
|
||||||
collections := generateIndexCollection(idx)
|
collections := generateIndexCollection(idx)
|
||||||
|
|
||||||
// if there are any external indexes being used by remote
|
|
||||||
// documents, then we need to search through them also.
|
|
||||||
externalIndexes := idx.GetAllExternalIndexes()
|
|
||||||
if len(externalIndexes) > 0 {
|
|
||||||
var extCollection []func() map[string]*index.Reference
|
|
||||||
for _, extIndex := range externalIndexes {
|
|
||||||
extCollection = generateIndexCollection(extIndex)
|
|
||||||
collections = append(collections, extCollection...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var found map[string]*index.Reference
|
var found map[string]*index.Reference
|
||||||
for _, collection := range collections {
|
for _, collection := range collections {
|
||||||
found = collection()
|
found = collection()
|
||||||
@@ -94,23 +89,107 @@ func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) (*yaml.Node, error) {
|
|||||||
if jh, _, _ := utils.IsNodeRefValue(found[rv].Node); jh {
|
if jh, _, _ := utils.IsNodeRefValue(found[rv].Node); jh {
|
||||||
// if this node is circular, stop drop and roll.
|
// if this node is circular, stop drop and roll.
|
||||||
if !IsCircular(found[rv].Node, idx) {
|
if !IsCircular(found[rv].Node, idx) {
|
||||||
return LocateRefNode(found[rv].Node, idx)
|
return LocateRefNodeWithContext(ctx, found[rv].Node, idx)
|
||||||
} else {
|
} else {
|
||||||
return found[rv].Node, fmt.Errorf("circular reference '%s' found during lookup at line "+
|
return found[rv].Node, idx, fmt.Errorf("circular reference '%s' found during lookup at line "+
|
||||||
"%d, column %d, It cannot be resolved",
|
"%d, column %d, It cannot be resolved",
|
||||||
GetCircularReferenceResult(found[rv].Node, idx).GenerateJourneyPath(),
|
GetCircularReferenceResult(found[rv].Node, idx).GenerateJourneyPath(),
|
||||||
found[rv].Node.Line,
|
found[rv].Node.Line,
|
||||||
found[rv].Node.Column)
|
found[rv].Node.Column), ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return utils.NodeAlias(found[rv].Node), nil
|
return utils.NodeAlias(found[rv].Node), idx, nil, ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// perform a search for the reference in the index
|
// perform a search for the reference in the index
|
||||||
foundRefs := idx.SearchIndexForReference(rv)
|
// extract the correct root
|
||||||
if len(foundRefs) > 0 {
|
specPath := idx.GetSpecAbsolutePath()
|
||||||
return utils.NodeAlias(foundRefs[0].Node), nil
|
if ctx.Value(index.CurrentPathKey) != nil {
|
||||||
|
specPath = ctx.Value(index.CurrentPathKey).(string)
|
||||||
|
}
|
||||||
|
|
||||||
|
explodedRefValue := strings.Split(rv, "#")
|
||||||
|
if len(explodedRefValue) == 2 {
|
||||||
|
if !strings.HasPrefix(explodedRefValue[0], "http") {
|
||||||
|
|
||||||
|
if !filepath.IsAbs(explodedRefValue[0]) {
|
||||||
|
|
||||||
|
if strings.HasPrefix(specPath, "http") {
|
||||||
|
u, _ := url.Parse(specPath)
|
||||||
|
p := ""
|
||||||
|
if u.Path != "" && explodedRefValue[0] != "" {
|
||||||
|
p = filepath.Dir(u.Path)
|
||||||
|
}
|
||||||
|
if p != "" && explodedRefValue[0] != "" {
|
||||||
|
u.Path = filepath.Join(p, explodedRefValue[0])
|
||||||
|
}
|
||||||
|
u.Fragment = ""
|
||||||
|
rv = fmt.Sprintf("%s#%s", u.String(), explodedRefValue[1])
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if specPath != "" {
|
||||||
|
var abs string
|
||||||
|
if explodedRefValue[0] == "" {
|
||||||
|
abs = specPath
|
||||||
|
} else {
|
||||||
|
abs, _ = filepath.Abs(filepath.Join(filepath.Dir(specPath), explodedRefValue[0]))
|
||||||
|
}
|
||||||
|
rv = fmt.Sprintf("%s#%s", abs, explodedRefValue[1])
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// check for a config baseURL and use that if it exists.
|
||||||
|
if idx.GetConfig().BaseURL != nil {
|
||||||
|
|
||||||
|
u := *idx.GetConfig().BaseURL
|
||||||
|
p := ""
|
||||||
|
if u.Path != "" {
|
||||||
|
p = filepath.Dir(u.Path)
|
||||||
|
}
|
||||||
|
u.Path = filepath.Join(p, explodedRefValue[0])
|
||||||
|
rv = fmt.Sprintf("%s#%s", u.String(), explodedRefValue[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if !strings.HasPrefix(explodedRefValue[0], "http") {
|
||||||
|
|
||||||
|
if !filepath.IsAbs(explodedRefValue[0]) {
|
||||||
|
|
||||||
|
if strings.HasPrefix(specPath, "http") {
|
||||||
|
u, _ := url.Parse(specPath)
|
||||||
|
p := filepath.Dir(u.Path)
|
||||||
|
abs, _ := filepath.Abs(filepath.Join(p, rv))
|
||||||
|
u.Path = abs
|
||||||
|
rv = u.String()
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if specPath != "" {
|
||||||
|
|
||||||
|
abs, _ := filepath.Abs(filepath.Join(filepath.Dir(specPath), rv))
|
||||||
|
rv = abs
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// check for a config baseURL and use that if it exists.
|
||||||
|
if idx.GetConfig().BaseURL != nil {
|
||||||
|
u := *idx.GetConfig().BaseURL
|
||||||
|
abs, _ := filepath.Abs(filepath.Join(u.Path, rv))
|
||||||
|
u.Path = abs
|
||||||
|
rv = u.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foundRef, fIdx, newCtx := idx.SearchIndexForReferenceWithContext(ctx, rv)
|
||||||
|
if foundRef != nil {
|
||||||
|
return utils.NodeAlias(foundRef.Node), fIdx, nil, newCtx
|
||||||
}
|
}
|
||||||
|
|
||||||
// let's try something else to find our references.
|
// let's try something else to find our references.
|
||||||
@@ -123,30 +202,40 @@ func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) (*yaml.Node, error) {
|
|||||||
nodes, fErr := path.Find(idx.GetRootNode())
|
nodes, fErr := path.Find(idx.GetRootNode())
|
||||||
if fErr == nil {
|
if fErr == nil {
|
||||||
if len(nodes) > 0 {
|
if len(nodes) > 0 {
|
||||||
return utils.NodeAlias(nodes[0]), nil
|
return utils.NodeAlias(nodes[0]), idx, nil, ctx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("reference '%s' at line %d, column %d was not found",
|
return nil, idx, fmt.Errorf("reference '%s' at line %d, column %d was not found",
|
||||||
rv, root.Line, root.Column)
|
rv, root.Line, root.Column), ctx
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, idx, nil, ctx
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// LocateRefNode will perform a complete lookup for a $ref node. This function searches the entire index for
|
||||||
|
// the reference being supplied. If there is a match found, the reference *yaml.Node is returned.
|
||||||
|
func LocateRefNode(root *yaml.Node, idx *index.SpecIndex) (*yaml.Node, *index.SpecIndex, error) {
|
||||||
|
r, i, e, _ := LocateRefNodeWithContext(context.Background(), root, idx)
|
||||||
|
return r, i, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractObjectRaw will extract a typed Buildable[N] object from a root yaml.Node. The 'raw' aspect is
|
// ExtractObjectRaw will extract a typed Buildable[N] object from a root yaml.Node. The 'raw' aspect is
|
||||||
// that there is no NodeReference wrapper around the result returned, just the raw object.
|
// that there is no NodeReference wrapper around the result returned, just the raw object.
|
||||||
func ExtractObjectRaw[T Buildable[N], N any](key, root *yaml.Node, idx *index.SpecIndex) (T, error, bool, string) {
|
func ExtractObjectRaw[T Buildable[N], N any](ctx context.Context, key, root *yaml.Node, idx *index.SpecIndex) (T, error, bool, string) {
|
||||||
var circError error
|
var circError error
|
||||||
var isReference bool
|
var isReference bool
|
||||||
var referenceValue string
|
var referenceValue string
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
if h, _, rv := utils.IsNodeRefValue(root); h {
|
if h, _, rv := utils.IsNodeRefValue(root); h {
|
||||||
ref, err := LocateRefNode(root, idx)
|
ref, fIdx, err, nCtx := LocateRefNodeWithContext(ctx, root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
root = ref
|
root = ref
|
||||||
isReference = true
|
isReference = true
|
||||||
referenceValue = rv
|
referenceValue = rv
|
||||||
|
idx = fIdx
|
||||||
|
ctx = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -161,7 +250,7 @@ func ExtractObjectRaw[T Buildable[N], N any](key, root *yaml.Node, idx *index.Sp
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err, isReference, referenceValue
|
return n, err, isReference, referenceValue
|
||||||
}
|
}
|
||||||
err = n.Build(key, root, idx)
|
err = n.Build(ctx, key, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return n, err, isReference, referenceValue
|
return n, err, isReference, referenceValue
|
||||||
}
|
}
|
||||||
@@ -180,19 +269,21 @@ func ExtractObjectRaw[T Buildable[N], N any](key, root *yaml.Node, idx *index.Sp
|
|||||||
|
|
||||||
// ExtractObject will extract a typed Buildable[N] object from a root yaml.Node. The result is wrapped in a
|
// ExtractObject will extract a typed Buildable[N] object from a root yaml.Node. The result is wrapped in a
|
||||||
// NodeReference[T] that contains the key node found and value node found when looking up the reference.
|
// NodeReference[T] that contains the key node found and value node found when looking up the reference.
|
||||||
func ExtractObject[T Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (NodeReference[T], error) {
|
func ExtractObject[T Buildable[N], N any](ctx context.Context, label string, root *yaml.Node, idx *index.SpecIndex) (NodeReference[T], error) {
|
||||||
var ln, vn *yaml.Node
|
var ln, vn *yaml.Node
|
||||||
var circError error
|
var circError error
|
||||||
var isReference bool
|
var isReference bool
|
||||||
var referenceValue string
|
var referenceValue string
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
if rf, rl, refVal := utils.IsNodeRefValue(root); rf {
|
if rf, rl, refVal := utils.IsNodeRefValue(root); rf {
|
||||||
ref, err := LocateRefNode(root, idx)
|
ref, fIdx, err, nCtx := LocateRefNodeWithContext(ctx, root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
vn = ref
|
vn = ref
|
||||||
ln = rl
|
ln = rl
|
||||||
isReference = true
|
isReference = true
|
||||||
referenceValue = refVal
|
referenceValue = refVal
|
||||||
|
idx = fIdx
|
||||||
|
ctx = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -205,9 +296,13 @@ func ExtractObject[T Buildable[N], N any](label string, root *yaml.Node, idx *in
|
|||||||
_, ln, vn = utils.FindKeyNodeFull(label, root.Content)
|
_, ln, vn = utils.FindKeyNodeFull(label, root.Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if h, _, rVal := utils.IsNodeRefValue(vn); h {
|
if h, _, rVal := utils.IsNodeRefValue(vn); h {
|
||||||
ref, lerr := LocateRefNode(vn, idx)
|
ref, fIdx, lerr, nCtx := LocateRefNodeWithContext(ctx, vn, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
vn = ref
|
vn = ref
|
||||||
|
if fIdx != nil {
|
||||||
|
idx = fIdx
|
||||||
|
}
|
||||||
|
ctx = nCtx
|
||||||
isReference = true
|
isReference = true
|
||||||
referenceValue = rVal
|
referenceValue = rVal
|
||||||
if lerr != nil {
|
if lerr != nil {
|
||||||
@@ -229,7 +324,7 @@ func ExtractObject[T Buildable[N], N any](label string, root *yaml.Node, idx *in
|
|||||||
if ln == nil {
|
if ln == nil {
|
||||||
return NodeReference[T]{}, nil
|
return NodeReference[T]{}, nil
|
||||||
}
|
}
|
||||||
err = n.Build(ln, vn, idx)
|
err = n.Build(ctx, ln, vn, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return NodeReference[T]{}, err
|
return NodeReference[T]{}, err
|
||||||
}
|
}
|
||||||
@@ -265,17 +360,21 @@ func SetReference(obj any, ref string) {
|
|||||||
|
|
||||||
// ExtractArray will extract a slice of []ValueReference[T] from a root yaml.Node that is defined as a sequence.
|
// ExtractArray will extract a slice of []ValueReference[T] from a root yaml.Node that is defined as a sequence.
|
||||||
// Used when the value being extracted is an array.
|
// Used when the value being extracted is an array.
|
||||||
func ExtractArray[T Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) ([]ValueReference[T],
|
func ExtractArray[T Buildable[N], N any](ctx context.Context, label string, root *yaml.Node, idx *index.SpecIndex) ([]ValueReference[T],
|
||||||
*yaml.Node, *yaml.Node, error,
|
*yaml.Node, *yaml.Node, error,
|
||||||
) {
|
) {
|
||||||
var ln, vn *yaml.Node
|
var ln, vn *yaml.Node
|
||||||
var circError error
|
var circError error
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
|
isRef := false
|
||||||
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
if rf, rl, _ := utils.IsNodeRefValue(root); rf {
|
||||||
ref, err := LocateRefNode(root, idx)
|
ref, fIdx, err, nCtx := LocateRefEnd(ctx, root, idx, 0)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
|
isRef = true
|
||||||
vn = ref
|
vn = ref
|
||||||
ln = rl
|
ln = rl
|
||||||
|
idx = fIdx
|
||||||
|
ctx = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -287,16 +386,19 @@ func ExtractArray[T Buildable[N], N any](label string, root *yaml.Node, idx *ind
|
|||||||
_, ln, vn = utils.FindKeyNodeFullTop(label, root.Content)
|
_, ln, vn = utils.FindKeyNodeFullTop(label, root.Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if h, _, _ := utils.IsNodeRefValue(vn); h {
|
if h, _, _ := utils.IsNodeRefValue(vn); h {
|
||||||
ref, err := LocateRefNode(vn, idx)
|
ref, fIdx, err, nCtx := LocateRefEnd(ctx, vn, idx, 0)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
|
isRef = true
|
||||||
vn = ref
|
vn = ref
|
||||||
//referenceValue = rVal
|
idx = fIdx
|
||||||
|
ctx = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []ValueReference[T]{}, nil, nil, fmt.Errorf("array build failed: reference cannot be found: %s",
|
return []ValueReference[T]{}, nil, nil,
|
||||||
|
fmt.Errorf("array build failed: reference cannot be found: %s",
|
||||||
err.Error())
|
err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,18 +409,33 @@ func ExtractArray[T Buildable[N], N any](label string, root *yaml.Node, idx *ind
|
|||||||
var items []ValueReference[T]
|
var items []ValueReference[T]
|
||||||
if vn != nil && ln != nil {
|
if vn != nil && ln != nil {
|
||||||
if !utils.IsNodeArray(vn) {
|
if !utils.IsNodeArray(vn) {
|
||||||
return []ValueReference[T]{}, nil, nil, fmt.Errorf("array build failed, input is not an array, line %d, column %d", vn.Line, vn.Column)
|
|
||||||
|
if !isRef {
|
||||||
|
return []ValueReference[T]{}, nil, nil,
|
||||||
|
fmt.Errorf("array build failed, input is not an array, line %d, column %d", vn.Line, vn.Column)
|
||||||
|
}
|
||||||
|
// if this was pulled from a ref, but it's not a sequence, check the label and see if anything comes out,
|
||||||
|
// and then check that is a sequence, if not, fail it.
|
||||||
|
_, _, fvn := utils.FindKeyNodeFullTop(label, vn.Content)
|
||||||
|
if fvn != nil {
|
||||||
|
if !utils.IsNodeArray(vn) {
|
||||||
|
return []ValueReference[T]{}, nil, nil,
|
||||||
|
fmt.Errorf("array build failed, input is not an array, line %d, column %d", vn.Line, vn.Column)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for _, node := range vn.Content {
|
for _, node := range vn.Content {
|
||||||
localReferenceValue := ""
|
localReferenceValue := ""
|
||||||
//localIsReference := false
|
foundCtx := ctx
|
||||||
|
foundIndex := idx
|
||||||
|
|
||||||
if rf, _, rv := utils.IsNodeRefValue(node); rf {
|
if rf, _, rv := utils.IsNodeRefValue(node); rf {
|
||||||
refg, err := LocateRefNode(node, idx)
|
refg, fIdx, err, nCtx := LocateRefEnd(ctx, node, idx, 0)
|
||||||
if refg != nil {
|
if refg != nil {
|
||||||
node = refg
|
node = refg
|
||||||
//localIsReference = true
|
|
||||||
localReferenceValue = rv
|
localReferenceValue = rv
|
||||||
|
foundIndex = fIdx
|
||||||
|
foundCtx = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -334,7 +451,7 @@ func ExtractArray[T Buildable[N], N any](label string, root *yaml.Node, idx *ind
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return []ValueReference[T]{}, ln, vn, err
|
return []ValueReference[T]{}, ln, vn, err
|
||||||
}
|
}
|
||||||
berr := n.Build(ln, node, idx)
|
berr := n.Build(foundCtx, ln, node, foundIndex)
|
||||||
if berr != nil {
|
if berr != nil {
|
||||||
return nil, ln, vn, berr
|
return nil, ln, vn, berr
|
||||||
}
|
}
|
||||||
@@ -381,6 +498,7 @@ func ExtractExample(expNode, expLabel *yaml.Node) NodeReference[any] {
|
|||||||
//
|
//
|
||||||
// This is useful when the node to be extracted, is already known and does not require a search.
|
// This is useful when the node to be extracted, is already known and does not require a search.
|
||||||
func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
||||||
|
ctx context.Context,
|
||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
includeExtensions bool,
|
includeExtensions bool,
|
||||||
@@ -417,15 +535,22 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
}
|
}
|
||||||
node = utils.NodeAlias(node)
|
node = utils.NodeAlias(node)
|
||||||
|
|
||||||
|
foundIndex := idx
|
||||||
|
foundContext := ctx
|
||||||
|
|
||||||
var isReference bool
|
var isReference bool
|
||||||
var referenceValue string
|
var referenceValue string
|
||||||
// if value is a reference, we have to look it up in the index!
|
// if value is a reference, we have to look it up in the index!
|
||||||
if h, _, rv := utils.IsNodeRefValue(node); h {
|
if h, _, rv := utils.IsNodeRefValue(node); h {
|
||||||
ref, err := LocateRefNode(node, idx)
|
ref, fIdx, err, nCtx := LocateRefNodeWithContext(ctx, node, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
node = ref
|
node = ref
|
||||||
isReference = true
|
isReference = true
|
||||||
referenceValue = rv
|
referenceValue = rv
|
||||||
|
if fIdx != nil {
|
||||||
|
foundIndex = fIdx
|
||||||
|
}
|
||||||
|
foundContext = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -435,13 +560,12 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var n PT = new(N)
|
var n PT = new(N)
|
||||||
err := BuildModel(node, n)
|
err := BuildModel(node, n)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
berr := n.Build(currentKey, node, idx)
|
berr := n.Build(foundContext, currentKey, node, foundIndex)
|
||||||
if berr != nil {
|
if berr != nil {
|
||||||
return nil, berr
|
return nil, berr
|
||||||
}
|
}
|
||||||
@@ -457,7 +581,6 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
ValueReference[PT]{
|
ValueReference[PT]{
|
||||||
Value: n,
|
Value: n,
|
||||||
ValueNode: node,
|
ValueNode: node,
|
||||||
//IsReference: isReference,
|
|
||||||
Reference: referenceValue,
|
Reference: referenceValue,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -477,10 +600,11 @@ func ExtractMapNoLookupExtensions[PT Buildable[N], N any](
|
|||||||
//
|
//
|
||||||
// This is useful when the node to be extracted, is already known and does not require a search.
|
// This is useful when the node to be extracted, is already known and does not require a search.
|
||||||
func ExtractMapNoLookup[PT Buildable[N], N any](
|
func ExtractMapNoLookup[PT Buildable[N], N any](
|
||||||
|
ctx context.Context,
|
||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], error) {
|
||||||
return ExtractMapNoLookupExtensions[PT, N](root, idx, false)
|
return ExtractMapNoLookupExtensions[PT, N](ctx, root, idx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
type mappingResult[T any] struct {
|
type mappingResult[T any] struct {
|
||||||
@@ -495,24 +619,25 @@ type mappingResult[T any] struct {
|
|||||||
// The second return value is the yaml.Node found for the 'label' and the third return value is the yaml.Node
|
// The second return value is the yaml.Node found for the 'label' and the third return value is the yaml.Node
|
||||||
// found for the value extracted from the label node.
|
// found for the value extracted from the label node.
|
||||||
func ExtractMapExtensions[PT Buildable[N], N any](
|
func ExtractMapExtensions[PT Buildable[N], N any](
|
||||||
|
ctx context.Context,
|
||||||
label string,
|
label string,
|
||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
extensions bool,
|
extensions bool,
|
||||||
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], *yaml.Node, *yaml.Node, error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], *yaml.Node, *yaml.Node, error) {
|
||||||
//var isReference bool
|
|
||||||
var referenceValue string
|
var referenceValue string
|
||||||
var labelNode, valueNode *yaml.Node
|
var labelNode, valueNode *yaml.Node
|
||||||
var circError error
|
var circError error
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
if rf, rl, rv := utils.IsNodeRefValue(root); rf {
|
if rf, rl, rv := utils.IsNodeRefValue(root); rf {
|
||||||
// locate reference in index.
|
// locate reference in index.
|
||||||
ref, err := LocateRefNode(root, idx)
|
ref, fIdx, err, fCtx := LocateRefNodeWithContext(ctx, root, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
valueNode = ref
|
valueNode = ref
|
||||||
labelNode = rl
|
labelNode = rl
|
||||||
//isReference = true
|
|
||||||
referenceValue = rv
|
referenceValue = rv
|
||||||
|
ctx = fCtx
|
||||||
|
idx = fIdx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -522,13 +647,15 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, labelNode, valueNode = utils.FindKeyNodeFull(label, root.Content)
|
_, labelNode, valueNode = utils.FindKeyNodeFull(label, root.Content)
|
||||||
|
valueNode = utils.NodeAlias(valueNode)
|
||||||
if valueNode != nil {
|
if valueNode != nil {
|
||||||
if h, _, rvt := utils.IsNodeRefValue(valueNode); h {
|
if h, _, rvt := utils.IsNodeRefValue(valueNode); h {
|
||||||
ref, err := LocateRefNode(valueNode, idx)
|
ref, fIdx, err, nCtx := LocateRefNodeWithContext(ctx, valueNode, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
valueNode = ref
|
valueNode = ref
|
||||||
//isReference = true
|
|
||||||
referenceValue = rvt
|
referenceValue = rvt
|
||||||
|
idx = fIdx
|
||||||
|
ctx = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -549,19 +676,17 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
bChan := make(chan mappingResult[PT])
|
bChan := make(chan mappingResult[PT])
|
||||||
eChan := make(chan error)
|
eChan := make(chan error)
|
||||||
|
|
||||||
buildMap := func(label *yaml.Node, value *yaml.Node, c chan mappingResult[PT], ec chan<- error, ref string) {
|
buildMap := func(nctx context.Context, label *yaml.Node, value *yaml.Node, c chan mappingResult[PT], ec chan<- error, ref string, fIdx *index.SpecIndex) {
|
||||||
var n PT = new(N)
|
var n PT = new(N)
|
||||||
value = utils.NodeAlias(value)
|
value = utils.NodeAlias(value)
|
||||||
_ = BuildModel(value, n)
|
_ = BuildModel(value, n)
|
||||||
err := n.Build(label, value, idx)
|
err := n.Build(nctx, label, value, fIdx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ec <- err
|
ec <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//isRef := false
|
|
||||||
if ref != "" {
|
if ref != "" {
|
||||||
//isRef = true
|
|
||||||
SetReference(n, ref)
|
SetReference(n, ref)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -573,7 +698,6 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
v: ValueReference[PT]{
|
v: ValueReference[PT]{
|
||||||
Value: n,
|
Value: n,
|
||||||
ValueNode: value,
|
ValueNode: value,
|
||||||
//IsReference: isRef,
|
|
||||||
Reference: ref,
|
Reference: ref,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@@ -587,12 +711,20 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
currentLabelNode = en
|
currentLabelNode = en
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foundIndex := idx
|
||||||
|
foundContext := ctx
|
||||||
|
|
||||||
// check our valueNode isn't a reference still.
|
// check our valueNode isn't a reference still.
|
||||||
if h, _, refVal := utils.IsNodeRefValue(en); h {
|
if h, _, refVal := utils.IsNodeRefValue(en); h {
|
||||||
ref, err := LocateRefNode(en, idx)
|
ref, fIdx, err, nCtx := LocateRefNodeWithContext(ctx, en, idx)
|
||||||
if ref != nil {
|
if ref != nil {
|
||||||
en = ref
|
en = ref
|
||||||
referenceValue = refVal
|
referenceValue = refVal
|
||||||
|
if fIdx != nil {
|
||||||
|
foundIndex = fIdx
|
||||||
|
}
|
||||||
|
foundContext = nCtx
|
||||||
if err != nil {
|
if err != nil {
|
||||||
circError = err
|
circError = err
|
||||||
}
|
}
|
||||||
@@ -610,7 +742,7 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
totalKeys++
|
totalKeys++
|
||||||
go buildMap(currentLabelNode, en, bChan, eChan, referenceValue)
|
go buildMap(foundContext, currentLabelNode, en, bChan, eChan, referenceValue, foundIndex)
|
||||||
}
|
}
|
||||||
|
|
||||||
completedKeys := 0
|
completedKeys := 0
|
||||||
@@ -637,11 +769,12 @@ func ExtractMapExtensions[PT Buildable[N], N any](
|
|||||||
// The second return value is the yaml.Node found for the 'label' and the third return value is the yaml.Node
|
// The second return value is the yaml.Node found for the 'label' and the third return value is the yaml.Node
|
||||||
// found for the value extracted from the label node.
|
// found for the value extracted from the label node.
|
||||||
func ExtractMap[PT Buildable[N], N any](
|
func ExtractMap[PT Buildable[N], N any](
|
||||||
|
ctx context.Context,
|
||||||
label string,
|
label string,
|
||||||
root *yaml.Node,
|
root *yaml.Node,
|
||||||
idx *index.SpecIndex,
|
idx *index.SpecIndex,
|
||||||
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], *yaml.Node, *yaml.Node, error) {
|
) (orderedmap.Map[KeyReference[string], ValueReference[PT]], *yaml.Node, *yaml.Node, error) {
|
||||||
return ExtractMapExtensions[PT, N](label, root, idx, false)
|
return ExtractMapExtensions[PT, N](ctx, label, root, idx, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExtractExtensions will extract any 'x-' prefixed key nodes from a root node into a map. Requirements have been pre-cast:
|
// ExtractExtensions will extract any 'x-' prefixed key nodes from a root node into a map. Requirements have been pre-cast:
|
||||||
@@ -714,6 +847,14 @@ func AreEqual(l, r Hashable) bool {
|
|||||||
if l == nil || r == nil {
|
if l == nil || r == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
vol := reflect.ValueOf(l)
|
||||||
|
vor := reflect.ValueOf(r)
|
||||||
|
|
||||||
|
if vol.Kind() != reflect.Struct && vor.Kind() != reflect.Struct {
|
||||||
|
if vol.IsNil() || vor.IsNil() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
return l.Hash() == r.Hash()
|
return l.Hash() == r.Hash()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -734,3 +875,23 @@ func GenerateHashString(v any) string {
|
|||||||
}
|
}
|
||||||
return fmt.Sprintf(HASH, sha256.Sum256([]byte(fmt.Sprint(v))))
|
return fmt.Sprintf(HASH, sha256.Sum256([]byte(fmt.Sprint(v))))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LocateRefEnd will perform a complete lookup for a $ref node. This function searches the entire index for
|
||||||
|
// the reference being supplied. If there is a match found, the reference *yaml.Node is returned.
|
||||||
|
// the function operates recursively and will keep iterating through references until it finds a non-reference
|
||||||
|
// node.
|
||||||
|
func LocateRefEnd(ctx context.Context, root *yaml.Node, idx *index.SpecIndex, depth int) (*yaml.Node, *index.SpecIndex, error, context.Context) {
|
||||||
|
depth++
|
||||||
|
if depth > 100 {
|
||||||
|
return nil, nil, fmt.Errorf("reference resolution depth exceeded, possible circular reference"), ctx
|
||||||
|
}
|
||||||
|
ref, fIdx, err, nCtx := LocateRefNodeWithContext(ctx, root, idx)
|
||||||
|
if err != nil {
|
||||||
|
return ref, fIdx, err, nCtx
|
||||||
|
}
|
||||||
|
if rf, _, _ := utils.IsNodeRefValue(ref); rf {
|
||||||
|
return LocateRefEnd(nCtx, ref, fIdx, depth)
|
||||||
|
} else {
|
||||||
|
return ref, fIdx, err, nCtx
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -96,8 +96,6 @@ type OpenAPIParameter interface {
|
|||||||
//TODO: this needs to be fixed, move returns to pointers.
|
//TODO: this needs to be fixed, move returns to pointers.
|
||||||
|
|
||||||
type SharedOperations interface {
|
type SharedOperations interface {
|
||||||
//HasDescription
|
|
||||||
//HasExternalDocs
|
|
||||||
GetOperationId() NodeReference[string]
|
GetOperationId() NodeReference[string]
|
||||||
GetExternalDocs() NodeReference[any]
|
GetExternalDocs() NodeReference[any]
|
||||||
GetDescription() NodeReference[string]
|
GetDescription() NodeReference[string]
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package low
|
package low
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
@@ -38,7 +39,7 @@ type IsReferenced interface {
|
|||||||
//
|
//
|
||||||
// Used by generic functions when automatically building out structs based on yaml.Node inputs.
|
// Used by generic functions when automatically building out structs based on yaml.Node inputs.
|
||||||
type Buildable[T any] interface {
|
type Buildable[T any] interface {
|
||||||
Build(key, value *yaml.Node, idx *index.SpecIndex) error
|
Build(ctx context.Context, key, value *yaml.Node, idx *index.SpecIndex) error
|
||||||
*T
|
*T
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +113,8 @@ type NodeReference[T any] struct {
|
|||||||
|
|
||||||
// If HasReference is true, then Reference contains the original $ref value.
|
// If HasReference is true, then Reference contains the original $ref value.
|
||||||
Reference string
|
Reference string
|
||||||
|
|
||||||
|
Context context.Context
|
||||||
}
|
}
|
||||||
|
|
||||||
// KeyReference is a low-level container for key nodes holding a Value of type T. A KeyNode is a pointer to the
|
// KeyReference is a low-level container for key nodes holding a Value of type T. A KeyNode is a pointer to the
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/resolver"
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
@@ -124,14 +123,14 @@ func TestIsCircular_LookupFromJourney(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Something'`
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, IsCircular(ref, idx))
|
assert.True(t, IsCircular(ref, idx))
|
||||||
}
|
}
|
||||||
@@ -157,14 +156,14 @@ func TestIsCircular_LookupFromJourney_Optional(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Something'`
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, IsCircular(ref, idx))
|
assert.True(t, IsCircular(ref, idx))
|
||||||
}
|
}
|
||||||
@@ -193,14 +192,14 @@ func TestIsCircular_LookupFromLoopPoint(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Nothing'`
|
yml = `$ref: '#/components/schemas/Nothing'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, IsCircular(ref, idx))
|
assert.True(t, IsCircular(ref, idx))
|
||||||
}
|
}
|
||||||
@@ -225,14 +224,14 @@ func TestIsCircular_LookupFromLoopPoint_Optional(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Nothing'`
|
yml = `$ref: '#/components/schemas/Nothing'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.True(t, IsCircular(ref, idx))
|
assert.True(t, IsCircular(ref, idx))
|
||||||
}
|
}
|
||||||
@@ -262,7 +261,7 @@ func TestIsCircular_FromRefLookup(t *testing.T) {
|
|||||||
assert.NoError(t, mErr)
|
assert.NoError(t, mErr)
|
||||||
idx := index.NewSpecIndex(&iNode)
|
idx := index.NewSpecIndex(&iNode)
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
@@ -298,7 +297,7 @@ func TestIsCircular_FromRefLookup_Optional(t *testing.T) {
|
|||||||
assert.NoError(t, mErr)
|
assert.NoError(t, mErr)
|
||||||
idx := index.NewSpecIndex(&iNode)
|
idx := index.NewSpecIndex(&iNode)
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
@@ -346,14 +345,14 @@ func TestGetCircularReferenceResult_FromJourney(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Something'`
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
circ := GetCircularReferenceResult(ref, idx)
|
circ := GetCircularReferenceResult(ref, idx)
|
||||||
assert.NotNil(t, circ)
|
assert.NotNil(t, circ)
|
||||||
@@ -380,14 +379,14 @@ func TestGetCircularReferenceResult_FromJourney_Optional(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Something'`
|
yml = `$ref: '#/components/schemas/Something'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
circ := GetCircularReferenceResult(ref, idx)
|
circ := GetCircularReferenceResult(ref, idx)
|
||||||
assert.NotNil(t, circ)
|
assert.NotNil(t, circ)
|
||||||
@@ -418,14 +417,14 @@ func TestGetCircularReferenceResult_FromLoopPoint(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Nothing'`
|
yml = `$ref: '#/components/schemas/Nothing'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
circ := GetCircularReferenceResult(ref, idx)
|
circ := GetCircularReferenceResult(ref, idx)
|
||||||
assert.NotNil(t, circ)
|
assert.NotNil(t, circ)
|
||||||
@@ -452,14 +451,14 @@ func TestGetCircularReferenceResult_FromLoopPoint_Optional(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Nothing'`
|
yml = `$ref: '#/components/schemas/Nothing'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
_ = yaml.Unmarshal([]byte(yml), &idxNode)
|
||||||
|
|
||||||
ref, err := LocateRefNode(idxNode.Content[0], idx)
|
ref, _, err := LocateRefNode(idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
circ := GetCircularReferenceResult(ref, idx)
|
circ := GetCircularReferenceResult(ref, idx)
|
||||||
assert.NotNil(t, circ)
|
assert.NotNil(t, circ)
|
||||||
@@ -490,7 +489,7 @@ func TestGetCircularReferenceResult_FromMappedRef(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Nothing'`
|
yml = `$ref: '#/components/schemas/Nothing'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 1)
|
assert.Len(t, errs, 1)
|
||||||
|
|
||||||
@@ -522,7 +521,7 @@ func TestGetCircularReferenceResult_FromMappedRef_Optional(t *testing.T) {
|
|||||||
|
|
||||||
yml = `$ref: '#/components/schemas/Nothing'`
|
yml = `$ref: '#/components/schemas/Nothing'`
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
@@ -545,7 +544,7 @@ func TestGetCircularReferenceResult_NothingFound(t *testing.T) {
|
|||||||
assert.NoError(t, mErr)
|
assert.NoError(t, mErr)
|
||||||
idx := index.NewSpecIndex(&iNode)
|
idx := index.NewSpecIndex(&iNode)
|
||||||
|
|
||||||
resolve := resolver.NewResolver(idx)
|
resolve := index.NewResolver(idx)
|
||||||
errs := resolve.CheckForCircularReferences()
|
errs := resolve.CheckForCircularReferences()
|
||||||
assert.Len(t, errs, 0)
|
assert.Len(t, errs, 0)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +0,0 @@
|
|||||||
// Copyright 2023 Princess B33f Heavy Industries / Dave Shanley
|
|
||||||
// SPDX-License-Identifier: MIT
|
|
||||||
|
|
||||||
package low
|
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -73,7 +74,7 @@ func (s *SecurityDefinitions) FindSecurityDefinition(securityDef string) *low.Va
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all definitions into SchemaProxy instances.
|
// Build will extract all definitions into SchemaProxy instances.
|
||||||
func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (d *Definitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
// TODO: Refactor with orderedmap.TranslatePipeline.
|
// TODO: Refactor with orderedmap.TranslatePipeline.
|
||||||
@@ -84,7 +85,7 @@ func (d *Definitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*base.SchemaProxy], e chan error) {
|
r chan definitionResult[*base.SchemaProxy], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*base.SchemaProxy](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*base.SchemaProxy](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
@@ -137,7 +138,7 @@ func (d *Definitions) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all ParameterDefinitions into Parameter instances.
|
// Build will extract all ParameterDefinitions into Parameter instances.
|
||||||
func (pd *ParameterDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (pd *ParameterDefinitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*Parameter])
|
resultChan := make(chan definitionResult[*Parameter])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -145,7 +146,7 @@ func (pd *ParameterDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex)
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*Parameter], e chan error) {
|
r chan definitionResult[*Parameter], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*Parameter](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*Parameter](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
@@ -187,7 +188,7 @@ type definitionResult[T any] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all ResponsesDefinitions into Response instances.
|
// Build will extract all ResponsesDefinitions into Response instances.
|
||||||
func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *ResponsesDefinitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*Response])
|
resultChan := make(chan definitionResult[*Response])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -195,7 +196,7 @@ func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) e
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*Response], e chan error) {
|
r chan definitionResult[*Response], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*Response](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*Response](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
@@ -231,7 +232,7 @@ func (r *ResponsesDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) e
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all SecurityDefinitions into SecurityScheme instances.
|
// Build will extract all SecurityDefinitions into SecurityScheme instances.
|
||||||
func (s *SecurityDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *SecurityDefinitions) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
errorChan := make(chan error)
|
errorChan := make(chan error)
|
||||||
resultChan := make(chan definitionResult[*SecurityScheme])
|
resultChan := make(chan definitionResult[*SecurityScheme])
|
||||||
var defLabel *yaml.Node
|
var defLabel *yaml.Node
|
||||||
@@ -240,7 +241,7 @@ func (s *SecurityDefinitions) Build(_, root *yaml.Node, idx *index.SpecIndex) er
|
|||||||
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
var buildFunc = func(label *yaml.Node, value *yaml.Node, idx *index.SpecIndex,
|
||||||
r chan definitionResult[*SecurityScheme], e chan error) {
|
r chan definitionResult[*SecurityScheme], e chan error) {
|
||||||
|
|
||||||
obj, err, _, rv := low.ExtractObjectRaw[*SecurityScheme](label, value, idx)
|
obj, err, _, rv := low.ExtractObjectRaw[*SecurityScheme](ctx, label, value, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -25,7 +26,7 @@ func TestDefinitions_Schemas_Build_Error(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func TestDefinitions_Parameters_Build_Error(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,7 +64,7 @@ func TestDefinitions_Hash(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Equal(t, "26d23786e6873e1a337f8e9be85f7de1490e4ff6cd303c3b15e593a25a6a149d",
|
assert.Equal(t, "26d23786e6873e1a337f8e9be85f7de1490e4ff6cd303c3b15e593a25a6a149d",
|
||||||
low.GenerateHashString(&n))
|
low.GenerateHashString(&n))
|
||||||
|
|
||||||
@@ -83,7 +84,7 @@ func TestDefinitions_Responses_Build_Error(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -102,7 +103,7 @@ func TestDefinitions_Security_Build_Error(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -29,7 +30,7 @@ func (e *Examples) FindExample(name string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all examples and will attempt to unmarshal content into a map or slice based on type.
|
// Build will extract all examples and will attempt to unmarshal content into a map or slice based on type.
|
||||||
func (e *Examples) Build(_, root *yaml.Node, _ *index.SpecIndex) error {
|
func (e *Examples) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
var keyNode, currNode *yaml.Node
|
var keyNode, currNode *yaml.Node
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -27,7 +28,7 @@ nothing: int`
|
|||||||
|
|
||||||
var n Examples
|
var n Examples
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `anything:
|
yml2 := `anything:
|
||||||
cake: burger
|
cake: burger
|
||||||
@@ -43,7 +44,7 @@ yes:
|
|||||||
|
|
||||||
var n2 Examples
|
var n2 Examples
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -51,11 +52,11 @@ func (h *Header) GetExtensions() map[low.KeyReference[string]]low.ValueReference
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will build out items, extensions and default value from the supplied node.
|
// Build will build out items, extensions and default value from the supplied node.
|
||||||
func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (h *Header) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
h.Extensions = low.ExtractExtensions(root)
|
h.Extensions = low.ExtractExtensions(root)
|
||||||
items, err := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
items, err := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -25,7 +26,7 @@ func TestHeader_Build(t *testing.T) {
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ default:
|
|||||||
|
|
||||||
var n Header
|
var n Header
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.NotNil(t, n.Default.Value)
|
assert.NotNil(t, n.Default.Value)
|
||||||
assert.Len(t, n.Default.Value, 3)
|
assert.Len(t, n.Default.Value, 3)
|
||||||
@@ -65,7 +66,7 @@ func TestHeader_DefaultAsObject(t *testing.T) {
|
|||||||
|
|
||||||
var n Header
|
var n Header
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.NotNil(t, n.Default.Value)
|
assert.NotNil(t, n.Default.Value)
|
||||||
}
|
}
|
||||||
@@ -80,7 +81,7 @@ func TestHeader_NoDefault(t *testing.T) {
|
|||||||
|
|
||||||
var n Header
|
var n Header
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.Equal(t, 12, n.Minimum.Value)
|
assert.Equal(t, 12, n.Minimum.Value)
|
||||||
}
|
}
|
||||||
@@ -116,7 +117,7 @@ multipleOf: 12`
|
|||||||
|
|
||||||
var n Header
|
var n Header
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `description: head
|
yml2 := `description: head
|
||||||
items:
|
items:
|
||||||
@@ -148,7 +149,7 @@ pattern: wow
|
|||||||
|
|
||||||
var n2 Header
|
var n2 Header
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -102,11 +103,11 @@ func (i *Items) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will build out items and default value.
|
// Build will build out items and default value.
|
||||||
func (i *Items) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (i *Items) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
i.Extensions = low.ExtractExtensions(root)
|
i.Extensions = low.ExtractExtensions(root)
|
||||||
items, iErr := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
items, iErr := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||||
if iErr != nil {
|
if iErr != nil {
|
||||||
return iErr
|
return iErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -25,7 +26,7 @@ func TestItems_Build(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ default:
|
|||||||
|
|
||||||
var n Items
|
var n Items
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.Len(t, n.Default.Value, 2)
|
assert.Len(t, n.Default.Value, 2)
|
||||||
assert.Len(t, n.GetExtensions(), 1)
|
assert.Len(t, n.GetExtensions(), 1)
|
||||||
@@ -60,7 +61,7 @@ func TestItems_DefaultAsMap(t *testing.T) {
|
|||||||
|
|
||||||
var n Items
|
var n Items
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
assert.Len(t, n.Default.Value, 2)
|
assert.Len(t, n.Default.Value, 2)
|
||||||
|
|
||||||
@@ -96,7 +97,7 @@ multipleOf: 12`
|
|||||||
|
|
||||||
var n Items
|
var n Items
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `items:
|
yml2 := `items:
|
||||||
type: int
|
type: int
|
||||||
@@ -127,7 +128,7 @@ pattern: wow
|
|||||||
|
|
||||||
var n2 Items
|
var n2 Items
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -36,20 +37,20 @@ type Operation struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract external docs, extensions, parameters, responses and security requirements.
|
// Build will extract external docs, extensions, parameters, responses and security requirements.
|
||||||
func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (o *Operation) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
o.Extensions = low.ExtractExtensions(root)
|
o.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, root, idx)
|
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, root, idx)
|
||||||
if dErr != nil {
|
if dErr != nil {
|
||||||
return dErr
|
return dErr
|
||||||
}
|
}
|
||||||
o.ExternalDocs = extDocs
|
o.ExternalDocs = extDocs
|
||||||
|
|
||||||
// extract parameters
|
// extract parameters
|
||||||
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
|
params, ln, vn, pErr := low.ExtractArray[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
if pErr != nil {
|
if pErr != nil {
|
||||||
return pErr
|
return pErr
|
||||||
}
|
}
|
||||||
@@ -62,14 +63,14 @@ func (o *Operation) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract responses
|
// extract responses
|
||||||
respBody, respErr := low.ExtractObject[*Responses](ResponsesLabel, root, idx)
|
respBody, respErr := low.ExtractObject[*Responses](ctx, ResponsesLabel, root, idx)
|
||||||
if respErr != nil {
|
if respErr != nil {
|
||||||
return respErr
|
return respErr
|
||||||
}
|
}
|
||||||
o.Responses = respBody
|
o.Responses = respBody
|
||||||
|
|
||||||
// extract security
|
// extract security
|
||||||
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
sec, sln, svn, sErr := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -28,7 +29,7 @@ func TestOperation_Build_ExternalDocs(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -47,7 +48,7 @@ func TestOperation_Build_Params(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -66,7 +67,7 @@ func TestOperation_Build_Responses(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -85,7 +86,7 @@ func TestOperation_Build_Security(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -128,7 +129,7 @@ x-smoke: not for a while`
|
|||||||
|
|
||||||
var n Operation
|
var n Operation
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `summary: a nice day
|
yml2 := `summary: a nice day
|
||||||
tags:
|
tags:
|
||||||
@@ -166,7 +167,7 @@ security:
|
|||||||
|
|
||||||
var n2 Operation
|
var n2 Operation
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -5,8 +5,10 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"io/ioutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// How to create a low-level Swagger / OpenAPI 2 Document from a specification
|
// How to create a low-level Swagger / OpenAPI 2 Document from a specification
|
||||||
@@ -15,18 +17,19 @@ func Example_createLowLevelSwaggerDocument() {
|
|||||||
// How to create a low-level OpenAPI 2 Document
|
// How to create a low-level OpenAPI 2 Document
|
||||||
|
|
||||||
// load petstore into bytes
|
// load petstore into bytes
|
||||||
petstoreBytes, _ := ioutil.ReadFile("../../../test_specs/petstorev2.json")
|
petstoreBytes, _ := os.ReadFile("../../../test_specs/petstorev2.json")
|
||||||
|
|
||||||
// read in specification
|
// read in specification
|
||||||
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
||||||
|
|
||||||
// build low-level document model
|
// build low-level document model
|
||||||
document, errors := CreateDocument(info)
|
document, err := CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
|
|
||||||
// if something went wrong, a slice of errors is returned
|
// if something went wrong, a slice of errors is returned
|
||||||
if len(errors) > 0 {
|
errs := utils.UnwrapErrors(err)
|
||||||
for i := range errors {
|
if len(errs) > 0 {
|
||||||
fmt.Printf("error: %s\n", errors[i].Error())
|
for i := range errs {
|
||||||
|
fmt.Printf("error: %s\n", errs[i].Error())
|
||||||
}
|
}
|
||||||
panic("cannot build document")
|
panic("cannot build document")
|
||||||
}
|
}
|
||||||
@@ -43,18 +46,19 @@ func ExampleCreateDocument() {
|
|||||||
// How to create a low-level OpenAPI 2 Document
|
// How to create a low-level OpenAPI 2 Document
|
||||||
|
|
||||||
// load petstore into bytes
|
// load petstore into bytes
|
||||||
petstoreBytes, _ := ioutil.ReadFile("../../../test_specs/petstorev2.json")
|
petstoreBytes, _ := os.ReadFile("../../../test_specs/petstorev2.json")
|
||||||
|
|
||||||
// read in specification
|
// read in specification
|
||||||
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
||||||
|
|
||||||
// build low-level document model
|
// build low-level document model
|
||||||
document, errors := CreateDocument(info)
|
document, err := CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
|
|
||||||
// if something went wrong, a slice of errors is returned
|
// if something went wrong, a slice of errors is returned
|
||||||
if len(errors) > 0 {
|
errs := utils.UnwrapErrors(err)
|
||||||
for i := range errors {
|
if len(errs) > 0 {
|
||||||
fmt.Printf("error: %s\n", errors[i].Error())
|
for i := range errs {
|
||||||
|
fmt.Printf("error: %s\n", errs[i].Error())
|
||||||
}
|
}
|
||||||
panic("cannot build document")
|
panic("cannot build document")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -94,18 +95,18 @@ func (p *Parameter) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract out extensions, schema, items and default value
|
// Build will extract out extensions, schema, items and default value
|
||||||
func (p *Parameter) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Parameter) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Extensions = low.ExtractExtensions(root)
|
p.Extensions = low.ExtractExtensions(root)
|
||||||
sch, sErr := base.ExtractSchema(root, idx)
|
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
if sch != nil {
|
if sch != nil {
|
||||||
p.Schema = *sch
|
p.Schema = *sch
|
||||||
}
|
}
|
||||||
items, iErr := low.ExtractObject[*Items](ItemsLabel, root, idx)
|
items, iErr := low.ExtractObject[*Items](ctx, ItemsLabel, root, idx)
|
||||||
if iErr != nil {
|
if iErr != nil {
|
||||||
return iErr
|
return iErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
@@ -25,7 +26,7 @@ func TestParameter_Build(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func TestParameter_Build_Items(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,7 +64,7 @@ func TestParameter_DefaultSlice(t *testing.T) {
|
|||||||
var n Parameter
|
var n Parameter
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
|
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Len(t, n.Default.Value.([]any), 3)
|
assert.Len(t, n.Default.Value.([]any), 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,7 +81,7 @@ func TestParameter_DefaultMap(t *testing.T) {
|
|||||||
var n Parameter
|
var n Parameter
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
|
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Len(t, n.Default.Value.(map[string]any), 2)
|
assert.Len(t, n.Default.Value.(map[string]any), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@ func TestParameter_NoDefaultNoError(t *testing.T) {
|
|||||||
var n Parameter
|
var n Parameter
|
||||||
_ = low.BuildModel(&idxNode, &n)
|
_ = low.BuildModel(&idxNode, &n)
|
||||||
|
|
||||||
err := n.Build(nil, idxNode.Content[0], idx)
|
err := n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +137,7 @@ required: true`
|
|||||||
|
|
||||||
var n Parameter
|
var n Parameter
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `items:
|
yml2 := `items:
|
||||||
type: int
|
type: int
|
||||||
@@ -174,7 +175,7 @@ allowEmptyValue: true
|
|||||||
|
|
||||||
var n2 Parameter
|
var n2 Parameter
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -48,7 +49,7 @@ func (p *PathItem) GetExtensions() map[low.KeyReference[string]]low.ValueReferen
|
|||||||
|
|
||||||
// Build will extract extensions, parameters and operations for all methods. Every method is handled
|
// Build will extract extensions, parameters and operations for all methods. Every method is handled
|
||||||
// asynchronously, in order to keep things moving quickly for complex operations.
|
// asynchronously, in order to keep things moving quickly for complex operations.
|
||||||
func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *PathItem) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Extensions = low.ExtractExtensions(root)
|
p.Extensions = low.ExtractExtensions(root)
|
||||||
@@ -61,7 +62,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
var ops []low.NodeReference[*Operation]
|
var ops []low.NodeReference[*Operation]
|
||||||
|
|
||||||
// extract parameters
|
// extract parameters
|
||||||
params, ln, vn, pErr := low.ExtractArray[*Parameter](ParametersLabel, root, idx)
|
params, ln, vn, pErr := low.ExtractArray[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
if pErr != nil {
|
if pErr != nil {
|
||||||
return pErr
|
return pErr
|
||||||
}
|
}
|
||||||
@@ -158,7 +159,7 @@ func (p *PathItem) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
opErrorChan := make(chan error)
|
opErrorChan := make(chan error)
|
||||||
|
|
||||||
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
|
var buildOpFunc = func(op low.NodeReference[*Operation], ch chan<- bool, errCh chan<- error) {
|
||||||
er := op.Value.Build(op.KeyNode, op.ValueNode, idx)
|
er := op.Value.Build(ctx, op.KeyNode, op.ValueNode, idx)
|
||||||
if er != nil {
|
if er != nil {
|
||||||
errCh <- er
|
errCh <- er
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -25,7 +26,7 @@ func TestPathItem_Build_Params(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func TestPathItem_Build_MethodFail(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -76,7 +77,7 @@ x-winter: is coming`
|
|||||||
|
|
||||||
var n PathItem
|
var n PathItem
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `post:
|
yml2 := `post:
|
||||||
description: post me there
|
description: post me there
|
||||||
@@ -103,7 +104,7 @@ parameters:
|
|||||||
|
|
||||||
var n2 PathItem
|
var n2 PathItem
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -58,7 +59,7 @@ func (p *Paths) FindExtension(ext string) *low.ValueReference[any] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and paths from node.
|
// Build will extract extensions and paths from node.
|
||||||
func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (p *Paths) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
p.Extensions = low.ExtractExtensions(root)
|
p.Extensions = low.ExtractExtensions(root)
|
||||||
@@ -130,7 +131,7 @@ func (p *Paths) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
cNode := value.currentNode
|
cNode := value.currentNode
|
||||||
path := new(PathItem)
|
path := new(PathItem)
|
||||||
_ = low.BuildModel(pNode, path)
|
_ = low.BuildModel(pNode, path)
|
||||||
err := path.Build(cNode, pNode, idx)
|
err := path.Build(ctx, cNode, pNode, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return pathBuildResult{}, err
|
return pathBuildResult{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -27,7 +28,7 @@ func TestPaths_Build(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -47,7 +48,7 @@ func TestPaths_FindPathAndKey(t *testing.T) {
|
|||||||
|
|
||||||
var n Paths
|
var n Paths
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
_, k := n.FindPathAndKey("/no/pizza")
|
_, k := n.FindPathAndKey("/no/pizza")
|
||||||
assert.Equal(t, "because i'm fat", k.Value.Post.Value.Description.Value)
|
assert.Equal(t, "because i'm fat", k.Value.Post.Value.Description.Value)
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ x-milk: creamy`
|
|||||||
|
|
||||||
var n Paths
|
var n Paths
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `x-milk: creamy
|
yml2 := `x-milk: creamy
|
||||||
/spl/unk:
|
/spl/unk:
|
||||||
@@ -94,7 +95,7 @@ x-milk: creamy`
|
|||||||
|
|
||||||
var n2 Paths
|
var n2 Paths
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
@@ -123,6 +124,6 @@ func TestPaths_Build_Fail_Many(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -45,11 +46,11 @@ func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract schema, extensions, examples and headers from node
|
// Build will extract schema, extensions, examples and headers from node
|
||||||
func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *Response) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
r.Extensions = low.ExtractExtensions(root)
|
r.Extensions = low.ExtractExtensions(root)
|
||||||
s, err := base.ExtractSchema(root, idx)
|
s, err := base.ExtractSchema(ctx, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -58,14 +59,14 @@ func (r *Response) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// extract examples
|
// extract examples
|
||||||
examples, expErr := low.ExtractObject[*Examples](ExamplesLabel, root, idx)
|
examples, expErr := low.ExtractObject[*Examples](ctx, ExamplesLabel, root, idx)
|
||||||
if expErr != nil {
|
if expErr != nil {
|
||||||
return expErr
|
return expErr
|
||||||
}
|
}
|
||||||
r.Examples = examples
|
r.Examples = examples
|
||||||
|
|
||||||
//extract headers
|
//extract headers
|
||||||
headers, lN, kN, err := low.ExtractMap[*Header](HeadersLabel, root, idx)
|
headers, lN, kN, err := low.ExtractMap[*Header](ctx, HeadersLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -25,7 +26,7 @@ func TestResponse_Build_Schema(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -44,7 +45,7 @@ func TestResponse_Build_Examples(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -63,7 +64,7 @@ func TestResponse_Build_Headers(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -87,7 +88,7 @@ x-herbs: missing`
|
|||||||
|
|
||||||
var n Response
|
var n Response
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `description: your thing, sir.
|
yml2 := `description: your thing, sir.
|
||||||
examples:
|
examples:
|
||||||
@@ -106,7 +107,7 @@ headers:
|
|||||||
|
|
||||||
var n2 Response
|
var n2 Response
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -29,13 +30,13 @@ func (r *Responses) GetExtensions() map[low.KeyReference[string]]low.ValueRefere
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract default value and extensions from node.
|
// Build will extract default value and extensions from node.
|
||||||
func (r *Responses) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (r *Responses) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
r.Extensions = low.ExtractExtensions(root)
|
r.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
if utils.IsNodeMap(root) {
|
if utils.IsNodeMap(root) {
|
||||||
codes, err := low.ExtractMapNoLookup[*Response](root, idx)
|
codes, err := low.ExtractMapNoLookup[*Response](ctx, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -24,7 +25,7 @@ func TestResponses_Build_Response(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -43,7 +44,7 @@ func TestResponses_Build_Response_Default(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -61,7 +62,7 @@ func TestResponses_Build_WrongType(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,7 @@ x-tea: warm
|
|||||||
|
|
||||||
var n Responses
|
var n Responses
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `401:
|
yml2 := `401:
|
||||||
description: and you are?
|
description: and you are?
|
||||||
@@ -110,7 +111,7 @@ x-tea: warm`
|
|||||||
|
|
||||||
var n2 Responses
|
var n2 Responses
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -36,7 +37,7 @@ func (s *Scopes) FindScope(scope string) *low.ValueReference[string] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract scope values and extensions from node.
|
// Build will extract scope values and extensions from node.
|
||||||
func (s *Scopes) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (s *Scopes) Build(_ context.Context, _, root *yaml.Node, _ *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
s.Extensions = low.ExtractExtensions(root)
|
s.Extensions = low.ExtractExtensions(root)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -23,7 +24,7 @@ x-men: needs a reboot or a refresh`
|
|||||||
|
|
||||||
var n Scopes
|
var n Scopes
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `x-men: needs a reboot or a refresh
|
yml2 := `x-men: needs a reboot or a refresh
|
||||||
pizza: beans
|
pizza: beans
|
||||||
@@ -35,7 +36,7 @@ burgers: chips`
|
|||||||
|
|
||||||
var n2 Scopes
|
var n2 Scopes
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -38,12 +39,12 @@ func (ss *SecurityScheme) GetExtensions() map[low.KeyReference[string]]low.Value
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions and scopes from the node.
|
// Build will extract extensions and scopes from the node.
|
||||||
func (ss *SecurityScheme) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (ss *SecurityScheme) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
ss.Extensions = low.ExtractExtensions(root)
|
ss.Extensions = low.ExtractExtensions(root)
|
||||||
|
|
||||||
scopes, sErr := low.ExtractObject[*Scopes](ScopesLabel, root, idx)
|
scopes, sErr := low.ExtractObject[*Scopes](ctx, ScopesLabel, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -27,7 +28,7 @@ func TestSecurityScheme_Build_Borked(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -47,7 +48,7 @@ func TestSecurityScheme_Build_Scopes(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 2, orderedmap.Len(n.Scopes.Value.Values))
|
assert.Equal(t, 2, orderedmap.Len(n.Scopes.Value.Values))
|
||||||
|
|
||||||
@@ -72,7 +73,7 @@ x-beer: not for a while`
|
|||||||
|
|
||||||
var n SecurityScheme
|
var n SecurityScheme
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `in: my heart
|
yml2 := `in: my heart
|
||||||
scopes:
|
scopes:
|
||||||
@@ -92,7 +93,7 @@ authorizationUrl: https://pb33f.io
|
|||||||
|
|
||||||
var n2 SecurityScheme
|
var n2 SecurityScheme
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -12,16 +12,18 @@
|
|||||||
package v2
|
package v2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
"errors"
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/resolver"
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
// processes a property of a Swagger document asynchronously using bool and error channels for signals.
|
// processes a property of a Swagger document asynchronously using bool and error channels for signals.
|
||||||
type documentFunction func(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error)
|
type documentFunction func(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error)
|
||||||
|
|
||||||
// Swagger represents a high-level Swagger / OpenAPI 2 document. An instance of Swagger is the root of the specification.
|
// Swagger represents a high-level Swagger / OpenAPI 2 document. An instance of Swagger is the root of the specification.
|
||||||
type Swagger struct {
|
type Swagger struct {
|
||||||
@@ -109,6 +111,10 @@ type Swagger struct {
|
|||||||
//
|
//
|
||||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||||
SpecInfo *datamodel.SpecInfo
|
SpecInfo *datamodel.SpecInfo
|
||||||
|
|
||||||
|
// Rolodex is a reference to the index.Rolodex instance created when the specification was read.
|
||||||
|
// The rolodex is used to look up references from file systems (local or remote)
|
||||||
|
Rolodex *index.Rolodex
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindExtension locates an extension from the root of the Swagger document.
|
// FindExtension locates an extension from the root of the Swagger document.
|
||||||
@@ -123,57 +129,100 @@ func (s *Swagger) GetExtensions() map[low.KeyReference[string]]low.ValueReferenc
|
|||||||
|
|
||||||
// CreateDocumentFromConfig will create a new Swagger document from the provided SpecInfo and DocumentConfiguration.
|
// CreateDocumentFromConfig will create a new Swagger document from the provided SpecInfo and DocumentConfiguration.
|
||||||
func CreateDocumentFromConfig(info *datamodel.SpecInfo,
|
func CreateDocumentFromConfig(info *datamodel.SpecInfo,
|
||||||
configuration *datamodel.DocumentConfiguration) (*Swagger, []error) {
|
configuration *datamodel.DocumentConfiguration) (*Swagger, error) {
|
||||||
return createDocument(info, configuration)
|
return createDocument(info, configuration)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDocument will create a new Swagger document from the provided SpecInfo.
|
func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfiguration) (*Swagger, error) {
|
||||||
//
|
|
||||||
// Deprecated: Use CreateDocumentFromConfig instead.
|
|
||||||
func CreateDocument(info *datamodel.SpecInfo) (*Swagger, []error) {
|
|
||||||
return createDocument(info, &datamodel.DocumentConfiguration{
|
|
||||||
AllowRemoteReferences: true,
|
|
||||||
AllowFileReferences: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfiguration) (*Swagger, []error) {
|
|
||||||
doc := Swagger{Swagger: low.ValueReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
doc := Swagger{Swagger: low.ValueReference[string]{Value: info.Version, ValueNode: info.RootNode}}
|
||||||
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
||||||
|
|
||||||
// build an index
|
// create an index config and shadow the document configuration.
|
||||||
idx := index.NewSpecIndexWithConfig(info.RootNode, &index.SpecIndexConfig{
|
idxConfig := index.CreateClosedAPIIndexConfig()
|
||||||
BaseURL: config.BaseURL,
|
idxConfig.SpecInfo = info
|
||||||
RemoteURLHandler: config.RemoteURLHandler,
|
idxConfig.IgnoreArrayCircularReferences = config.IgnoreArrayCircularReferences
|
||||||
AllowRemoteLookup: config.AllowRemoteReferences,
|
idxConfig.IgnorePolymorphicCircularReferences = config.IgnorePolymorphicCircularReferences
|
||||||
AllowFileLookup: config.AllowFileReferences,
|
idxConfig.AvoidCircularReferenceCheck = true
|
||||||
})
|
idxConfig.BaseURL = config.BaseURL
|
||||||
doc.Index = idx
|
idxConfig.BasePath = config.BasePath
|
||||||
doc.SpecInfo = info
|
idxConfig.Logger = config.Logger
|
||||||
|
rolodex := index.NewRolodex(idxConfig)
|
||||||
|
rolodex.SetRootNode(info.RootNode)
|
||||||
|
doc.Rolodex = rolodex
|
||||||
|
|
||||||
var errors []error
|
// If basePath is provided, add a local filesystem to the rolodex.
|
||||||
|
if idxConfig.BasePath != "" {
|
||||||
|
var cwd string
|
||||||
|
cwd, _ = filepath.Abs(config.BasePath)
|
||||||
|
// if a supplied local filesystem is provided, add it to the rolodex.
|
||||||
|
if config.LocalFS != nil {
|
||||||
|
rolodex.AddLocalFS(cwd, config.LocalFS)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// create a local filesystem
|
||||||
|
localFSConf := index.LocalFSConfig{
|
||||||
|
BaseDirectory: cwd,
|
||||||
|
IndexConfig: idxConfig,
|
||||||
|
FileFilters: config.FileFilter,
|
||||||
|
}
|
||||||
|
fileFS, _ := index.NewLocalFSWithConfig(&localFSConf)
|
||||||
|
idxConfig.AllowFileLookup = true
|
||||||
|
|
||||||
|
// add the filesystem to the rolodex
|
||||||
|
rolodex.AddLocalFS(cwd, fileFS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if base url is provided, add a remote filesystem to the rolodex.
|
||||||
|
if idxConfig.BaseURL != nil {
|
||||||
|
|
||||||
|
// create a remote filesystem
|
||||||
|
remoteFS, _ := index.NewRemoteFSWithConfig(idxConfig)
|
||||||
|
if config.RemoteURLHandler != nil {
|
||||||
|
remoteFS.RemoteHandlerFunc = config.RemoteURLHandler
|
||||||
|
}
|
||||||
|
idxConfig.AllowRemoteLookup = true
|
||||||
|
|
||||||
|
// add to the rolodex
|
||||||
|
rolodex.AddRemoteFS(config.BaseURL.String(), remoteFS)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
doc.Rolodex = rolodex
|
||||||
|
|
||||||
|
var errs []error
|
||||||
|
|
||||||
|
// index all the things!
|
||||||
|
_ = rolodex.IndexTheRolodex()
|
||||||
|
|
||||||
|
// check for circular references
|
||||||
|
if !config.SkipCircularReferenceCheck {
|
||||||
|
rolodex.CheckForCircularReferences()
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract errors
|
||||||
|
roloErrs := rolodex.GetCaughtErrors()
|
||||||
|
if roloErrs != nil {
|
||||||
|
errs = append(errs, roloErrs...)
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the index on the document.
|
||||||
|
doc.Index = rolodex.GetRootIndex()
|
||||||
|
doc.SpecInfo = info
|
||||||
|
|
||||||
// build out swagger scalar variables.
|
// build out swagger scalar variables.
|
||||||
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
_ = low.BuildModel(info.RootNode.Content[0], &doc)
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
// extract externalDocs
|
// extract externalDocs
|
||||||
extDocs, err := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode, idx)
|
extDocs, err := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, info.RootNode, rolodex.GetRootIndex())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errors = append(errors, err)
|
errs = append(errs, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
doc.ExternalDocs = extDocs
|
doc.ExternalDocs = extDocs
|
||||||
|
|
||||||
// create resolver and check for circular references.
|
|
||||||
resolve := resolver.NewResolver(idx)
|
|
||||||
resolvingErrors := resolve.CheckForCircularReferences()
|
|
||||||
|
|
||||||
if len(resolvingErrors) > 0 {
|
|
||||||
for r := range resolvingErrors {
|
|
||||||
errors = append(errors, resolvingErrors[r])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
extractionFuncs := []documentFunction{
|
extractionFuncs := []documentFunction{
|
||||||
extractInfo,
|
extractInfo,
|
||||||
extractPaths,
|
extractPaths,
|
||||||
@@ -187,7 +236,7 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
doneChan := make(chan bool)
|
doneChan := make(chan bool)
|
||||||
errChan := make(chan error)
|
errChan := make(chan error)
|
||||||
for i := range extractionFuncs {
|
for i := range extractionFuncs {
|
||||||
go extractionFuncs[i](info.RootNode.Content[0], &doc, idx, doneChan, errChan)
|
go extractionFuncs[i](ctx, info.RootNode.Content[0], &doc, rolodex.GetRootIndex(), doneChan, errChan)
|
||||||
}
|
}
|
||||||
completedExtractions := 0
|
completedExtractions := 0
|
||||||
for completedExtractions < len(extractionFuncs) {
|
for completedExtractions < len(extractionFuncs) {
|
||||||
@@ -196,11 +245,11 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
completedExtractions++
|
completedExtractions++
|
||||||
case e := <-errChan:
|
case e := <-errChan:
|
||||||
completedExtractions++
|
completedExtractions++
|
||||||
errors = append(errors, e)
|
errs = append(errs, e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &doc, errors
|
return &doc, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Swagger) GetExternalDocs() *low.NodeReference[any] {
|
func (s *Swagger) GetExternalDocs() *low.NodeReference[any] {
|
||||||
@@ -211,8 +260,8 @@ func (s *Swagger) GetExternalDocs() *low.NodeReference[any] {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractInfo(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractInfo(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
info, err := low.ExtractObject[*base.Info](base.InfoLabel, root, idx)
|
info, err := low.ExtractObject[*base.Info](ctx, base.InfoLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -221,8 +270,8 @@ func extractInfo(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractPaths(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
paths, err := low.ExtractObject[*Paths](PathsLabel, root, idx)
|
paths, err := low.ExtractObject[*Paths](ctx, PathsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -230,8 +279,8 @@ func extractPaths(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<-
|
|||||||
doc.Paths = paths
|
doc.Paths = paths
|
||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
def, err := low.ExtractObject[*Definitions](DefinitionsLabel, root, idx)
|
def, err := low.ExtractObject[*Definitions](ctx, DefinitionsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -239,8 +288,8 @@ func extractDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c c
|
|||||||
doc.Definitions = def
|
doc.Definitions = def
|
||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractParamDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
param, err := low.ExtractObject[*ParameterDefinitions](ParametersLabel, root, idx)
|
param, err := low.ExtractObject[*ParameterDefinitions](ctx, ParametersLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -249,8 +298,8 @@ func extractParamDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractResponsesDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
resp, err := low.ExtractObject[*ResponsesDefinitions](ResponsesLabel, root, idx)
|
resp, err := low.ExtractObject[*ResponsesDefinitions](ctx, ResponsesLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -259,8 +308,8 @@ func extractResponsesDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecI
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractSecurityDefinitions(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
sec, err := low.ExtractObject[*SecurityDefinitions](SecurityDefinitionsLabel, root, idx)
|
sec, err := low.ExtractObject[*SecurityDefinitions](ctx, SecurityDefinitionsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -269,8 +318,8 @@ func extractSecurityDefinitions(root *yaml.Node, doc *Swagger, idx *index.SpecIn
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractTags(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
tags, ln, vn, err := low.ExtractArray[*base.Tag](base.TagsLabel, root, idx)
|
tags, ln, vn, err := low.ExtractArray[*base.Tag](ctx, base.TagsLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
@@ -283,8 +332,8 @@ func extractTags(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- b
|
|||||||
c <- true
|
c <- true
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSecurity(root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
func extractSecurity(ctx context.Context, root *yaml.Node, doc *Swagger, idx *index.SpecIndex, c chan<- bool, e chan<- error) {
|
||||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, root, idx)
|
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
e <- err
|
e <- err
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
@@ -19,13 +23,10 @@ func initTest() {
|
|||||||
if doc != nil {
|
if doc != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
data, _ := os.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -40,13 +41,10 @@ func initTest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCreateDocument(b *testing.B) {
|
func BenchmarkCreateDocument(b *testing.B) {
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
data, _ := os.ReadFile("../../../test_specs/petstorev2-complete.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
doc, _ = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
doc, _ = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -184,8 +182,8 @@ func TestCreateDocument_ExternalDocsBad(t *testing.T) {
|
|||||||
$ref: bork`
|
$ref: bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -193,7 +191,7 @@ func TestCreateDocument_ExternalDocsBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_TagsBad(t *testing.T) {
|
func TestCreateDocument_TagsBad(t *testing.T) {
|
||||||
@@ -202,8 +200,8 @@ func TestCreateDocument_TagsBad(t *testing.T) {
|
|||||||
$ref: bork`
|
$ref: bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -211,7 +209,7 @@ func TestCreateDocument_TagsBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_PathsBad(t *testing.T) {
|
func TestCreateDocument_PathsBad(t *testing.T) {
|
||||||
@@ -224,8 +222,8 @@ func TestCreateDocument_PathsBad(t *testing.T) {
|
|||||||
$ref: bork`
|
$ref: bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -233,7 +231,7 @@ func TestCreateDocument_PathsBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_SecurityBad(t *testing.T) {
|
func TestCreateDocument_SecurityBad(t *testing.T) {
|
||||||
@@ -242,8 +240,8 @@ func TestCreateDocument_SecurityBad(t *testing.T) {
|
|||||||
$ref: `
|
$ref: `
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -251,7 +249,7 @@ func TestCreateDocument_SecurityBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_SecurityDefinitionsBad(t *testing.T) {
|
func TestCreateDocument_SecurityDefinitionsBad(t *testing.T) {
|
||||||
@@ -260,8 +258,8 @@ func TestCreateDocument_SecurityDefinitionsBad(t *testing.T) {
|
|||||||
$ref: `
|
$ref: `
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -269,7 +267,7 @@ func TestCreateDocument_SecurityDefinitionsBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_ResponsesBad(t *testing.T) {
|
func TestCreateDocument_ResponsesBad(t *testing.T) {
|
||||||
@@ -278,8 +276,8 @@ func TestCreateDocument_ResponsesBad(t *testing.T) {
|
|||||||
$ref: `
|
$ref: `
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -287,7 +285,7 @@ func TestCreateDocument_ResponsesBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_ParametersBad(t *testing.T) {
|
func TestCreateDocument_ParametersBad(t *testing.T) {
|
||||||
@@ -296,8 +294,8 @@ func TestCreateDocument_ParametersBad(t *testing.T) {
|
|||||||
$ref: `
|
$ref: `
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -305,7 +303,7 @@ func TestCreateDocument_ParametersBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_DefinitionsBad(t *testing.T) {
|
func TestCreateDocument_DefinitionsBad(t *testing.T) {
|
||||||
@@ -314,8 +312,8 @@ func TestCreateDocument_DefinitionsBad(t *testing.T) {
|
|||||||
$ref: `
|
$ref: `
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -323,7 +321,7 @@ func TestCreateDocument_DefinitionsBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_InfoBad(t *testing.T) {
|
func TestCreateDocument_InfoBad(t *testing.T) {
|
||||||
@@ -332,8 +330,8 @@ func TestCreateDocument_InfoBad(t *testing.T) {
|
|||||||
$ref: `
|
$ref: `
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
wait := true
|
wait := true
|
||||||
for wait {
|
for wait {
|
||||||
select {
|
select {
|
||||||
@@ -341,15 +339,151 @@ func TestCreateDocument_InfoBad(t *testing.T) {
|
|||||||
wait = false
|
wait = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert.Len(t, err, 1)
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularReferenceError(t *testing.T) {
|
func TestCircularReferenceError(t *testing.T) {
|
||||||
|
|
||||||
data, _ := ioutil.ReadFile("../../../test_specs/swagger-circular-tests.yaml")
|
data, _ := os.ReadFile("../../../test_specs/swagger-circular-tests.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
circDoc, err := CreateDocument(info)
|
circDoc, err := CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
assert.NotNil(t, circDoc)
|
assert.NotNil(t, circDoc)
|
||||||
assert.Len(t, err, 3)
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = "../../../test_specs"
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem_ProvideNonRolodexFS(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
baseDir := "../../../test_specs"
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = baseDir
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
cf.LocalFS = os.DirFS(baseDir)
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem_ProvideRolodexFS(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
baseDir := "../../../test_specs"
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = baseDir
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
|
||||||
|
localFS, lErr := index.NewLocalFSWithConfig(&index.LocalFSConfig{
|
||||||
|
BaseDirectory: baseDir,
|
||||||
|
DirFS: os.DirFS(baseDir),
|
||||||
|
FileFilters: cf.FileFilter,
|
||||||
|
})
|
||||||
|
cf.LocalFS = localFS
|
||||||
|
|
||||||
|
assert.NoError(t, lErr)
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem_BadPath(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = "/NOWHERE"
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
|
||||||
|
baseUrl := "https://raw.githubusercontent.com/pb33f/libopenapi/main/test_specs"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_BadBase(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
|
||||||
|
baseUrl := "https://no-no-this-will-not-work-it-just-will-not-get-the-job-done-mate.com"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_CustomRemote_NoBaseURL(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.RemoteFS, _ = index.NewRemoteFSWithConfig(&index.SpecIndexConfig{})
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_CustomHttpHandler(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.RemoteURLHandler = http.Get
|
||||||
|
baseUrl := "https://no-no-this-will-not-work-it-just-will-not-get-the-job-done-mate.com"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
|
||||||
|
pizza := func(url string) (resp *http.Response, err error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
cf.RemoteURLHandler = pizza
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_FailRemoteFS(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.RemoteURLHandler = http.Get
|
||||||
|
baseUrl := "https://no-no-this-will-not-work-it-just-will-not-get-the-job-done-mate.com"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
|
||||||
|
pizza := func(url string) (resp *http.Response, err error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
cf.RemoteURLHandler = pizza
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -41,7 +42,7 @@ func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions, expressions and PathItem objects for Callback
|
// Build will extract extensions, expressions and PathItem objects for Callback
|
||||||
func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (cb *Callback) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
cb.Reference = new(low.Reference)
|
cb.Reference = new(low.Reference)
|
||||||
@@ -59,7 +60,7 @@ func (cb *Callback) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
if strings.HasPrefix(currentCB.Value, "x-") {
|
if strings.HasPrefix(currentCB.Value, "x-") {
|
||||||
continue // ignore extension.
|
continue // ignore extension.
|
||||||
}
|
}
|
||||||
callback, eErr, _, rv := low.ExtractObjectRaw[*PathItem](currentCB, callbackNode, idx)
|
callback, eErr, _, rv := low.ExtractObjectRaw[*PathItem](ctx, currentCB, callbackNode, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
@@ -35,7 +36,7 @@ func TestCallback_Build_Success(t *testing.T) {
|
|||||||
err := low.BuildModel(rootNode.Content[0], &n)
|
err := low.BuildModel(rootNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, rootNode.Content[0], nil)
|
err = n.Build(context.Background(), nil, rootNode.Content[0], nil)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, 1, orderedmap.Len(n.Expression.Value))
|
assert.Equal(t, 1, orderedmap.Len(n.Expression.Value))
|
||||||
@@ -67,7 +68,7 @@ func TestCallback_Build_Error(t *testing.T) {
|
|||||||
err := low.BuildModel(rootNode.Content[0], &n)
|
err := low.BuildModel(rootNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, rootNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, rootNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -102,7 +103,7 @@ func TestCallback_Build_Using_InlineRef(t *testing.T) {
|
|||||||
err := low.BuildModel(rootNode.Content[0], &n)
|
err := low.BuildModel(rootNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, rootNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, rootNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, 1, orderedmap.Len(n.Expression.Value))
|
assert.Equal(t, 1, orderedmap.Len(n.Expression.Value))
|
||||||
|
|
||||||
@@ -130,7 +131,7 @@ x-weed: loved`
|
|||||||
|
|
||||||
var n Callback
|
var n Callback
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `burgers:
|
yml2 := `burgers:
|
||||||
description: tasty!
|
description: tasty!
|
||||||
@@ -147,7 +148,7 @@ beer:
|
|||||||
|
|
||||||
var n2 Callback
|
var n2 Callback
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -142,7 +143,7 @@ func (co *Components) FindCallback(callback string) *low.ValueReference[*Callbac
|
|||||||
|
|
||||||
// Build converts root YAML node containing components to low level model.
|
// Build converts root YAML node containing components to low level model.
|
||||||
// Process each component in parallel.
|
// Process each component in parallel.
|
||||||
func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
func (co *Components) Build(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
co.Reference = new(low.Reference)
|
co.Reference = new(low.Reference)
|
||||||
@@ -162,55 +163,55 @@ func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
schemas, err := extractComponentValues[*base.SchemaProxy](SchemasLabel, root, idx)
|
schemas, err := extractComponentValues[*base.SchemaProxy](ctx, SchemasLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Schemas = schemas
|
co.Schemas = schemas
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
parameters, err := extractComponentValues[*Parameter](ParametersLabel, root, idx)
|
parameters, err := extractComponentValues[*Parameter](ctx, ParametersLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Parameters = parameters
|
co.Parameters = parameters
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
responses, err := extractComponentValues[*Response](ResponsesLabel, root, idx)
|
responses, err := extractComponentValues[*Response](ctx, ResponsesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Responses = responses
|
co.Responses = responses
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
examples, err := extractComponentValues[*base.Example](base.ExamplesLabel, root, idx)
|
examples, err := extractComponentValues[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Examples = examples
|
co.Examples = examples
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
requestBodies, err := extractComponentValues[*RequestBody](RequestBodiesLabel, root, idx)
|
requestBodies, err := extractComponentValues[*RequestBody](ctx, RequestBodiesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.RequestBodies = requestBodies
|
co.RequestBodies = requestBodies
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
headers, err := extractComponentValues[*Header](HeadersLabel, root, idx)
|
headers, err := extractComponentValues[*Header](ctx, HeadersLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Headers = headers
|
co.Headers = headers
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
securitySchemes, err := extractComponentValues[*SecurityScheme](SecuritySchemesLabel, root, idx)
|
securitySchemes, err := extractComponentValues[*SecurityScheme](ctx, SecuritySchemesLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.SecuritySchemes = securitySchemes
|
co.SecuritySchemes = securitySchemes
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
links, err := extractComponentValues[*Link](LinksLabel, root, idx)
|
links, err := extractComponentValues[*Link](ctx, LinksLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Links = links
|
co.Links = links
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}()
|
}()
|
||||||
go func() {
|
go func() {
|
||||||
callbacks, err := extractComponentValues[*Callback](CallbacksLabel, root, idx)
|
callbacks, err := extractComponentValues[*Callback](ctx, CallbacksLabel, root, idx)
|
||||||
captureError(err)
|
captureError(err)
|
||||||
co.Callbacks = callbacks
|
co.Callbacks = callbacks
|
||||||
wg.Done()
|
wg.Done()
|
||||||
@@ -223,7 +224,7 @@ func (co *Components) Build(root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
// extractComponentValues converts all the YAML nodes of a component type to
|
// extractComponentValues converts all the YAML nodes of a component type to
|
||||||
// low level model.
|
// low level model.
|
||||||
// Process each node in parallel.
|
// Process each node in parallel.
|
||||||
func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.Node, idx *index.SpecIndex) (low.NodeReference[orderedmap.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[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]], error) {
|
||||||
var emptyResult low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]]
|
var emptyResult low.NodeReference[orderedmap.Map[low.KeyReference[string], low.ValueReference[T]]]
|
||||||
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
_, nodeLabel, nodeValue := utils.FindKeyNodeFullTop(label, root.Content)
|
||||||
if nodeValue == nil {
|
if nodeValue == nil {
|
||||||
@@ -289,7 +290,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
|||||||
// TODO: check circular crazy on this. It may explode
|
// TODO: check circular crazy on this. It may explode
|
||||||
var err error
|
var err error
|
||||||
if h, _, _ := utils.IsNodeRefValue(node); h && label != SchemasLabel {
|
if h, _, _ := utils.IsNodeRefValue(node); h && label != SchemasLabel {
|
||||||
node, err = low.LocateRefNode(node, idx)
|
node, _, err = low.LocateRefNode(node, idx)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return componentBuildResult[T]{}, err
|
return componentBuildResult[T]{}, err
|
||||||
@@ -297,7 +298,7 @@ func extractComponentValues[T low.Buildable[N], N any](label string, root *yaml.
|
|||||||
|
|
||||||
// build.
|
// build.
|
||||||
_ = low.BuildModel(node, n)
|
_ = low.BuildModel(node, n)
|
||||||
err = n.Build(currentLabel, node, idx)
|
err = n.Build(ctx, currentLabel, node, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return componentBuildResult[T]{}, err
|
return componentBuildResult[T]{}, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -66,7 +67,6 @@ var testComponentsYaml = `
|
|||||||
description: eighteen of many`
|
description: eighteen of many`
|
||||||
|
|
||||||
func TestComponents_Build_Success(t *testing.T) {
|
func TestComponents_Build_Success(t *testing.T) {
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
mErr := yaml.Unmarshal([]byte(testComponentsYaml), &idxNode)
|
mErr := yaml.Unmarshal([]byte(testComponentsYaml), &idxNode)
|
||||||
assert.NoError(t, mErr)
|
assert.NoError(t, mErr)
|
||||||
@@ -76,7 +76,7 @@ func TestComponents_Build_Success(t *testing.T) {
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, "one of many", n.FindSchema("one").Value.Schema().Description.Value)
|
assert.Equal(t, "one of many", n.FindSchema("one").Value.Schema().Description.Value)
|
||||||
@@ -102,11 +102,9 @@ func TestComponents_Build_Success(t *testing.T) {
|
|||||||
|
|
||||||
assert.Equal(t, "7add1a6c63a354b1a8ffe22552c213fe26d1229beb0b0cbe7c7ca06e63f9a364",
|
assert.Equal(t, "7add1a6c63a354b1a8ffe22552c213fe26d1229beb0b0cbe7c7ca06e63f9a364",
|
||||||
low.GenerateHashString(&n))
|
low.GenerateHashString(&n))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComponents_Build_Success_Skip(t *testing.T) {
|
func TestComponents_Build_Success_Skip(t *testing.T) {
|
||||||
|
|
||||||
yml := `components:`
|
yml := `components:`
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
@@ -118,13 +116,11 @@ func TestComponents_Build_Success_Skip(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComponents_Build_Fail(t *testing.T) {
|
func TestComponents_Build_Fail(t *testing.T) {
|
||||||
|
|
||||||
yml := `
|
yml := `
|
||||||
parameters:
|
parameters:
|
||||||
schema:
|
schema:
|
||||||
@@ -139,13 +135,11 @@ func TestComponents_Build_Fail(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComponents_Build_ParameterFail(t *testing.T) {
|
func TestComponents_Build_ParameterFail(t *testing.T) {
|
||||||
|
|
||||||
yml := `
|
yml := `
|
||||||
parameters:
|
parameters:
|
||||||
pizza:
|
pizza:
|
||||||
@@ -161,9 +155,8 @@ func TestComponents_Build_ParameterFail(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test parse failure among many parameters.
|
// Test parse failure among many parameters.
|
||||||
@@ -191,12 +184,11 @@ func TestComponents_Build_ParameterFail_Many(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComponents_Build_Fail_TypeFail(t *testing.T) {
|
func TestComponents_Build_Fail_TypeFail(t *testing.T) {
|
||||||
|
|
||||||
yml := `
|
yml := `
|
||||||
parameters:
|
parameters:
|
||||||
- schema:
|
- schema:
|
||||||
@@ -211,12 +203,11 @@ func TestComponents_Build_Fail_TypeFail(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComponents_Build_ExtensionTest(t *testing.T) {
|
func TestComponents_Build_ExtensionTest(t *testing.T) {
|
||||||
|
|
||||||
yml := `x-curry: seagull
|
yml := `x-curry: seagull
|
||||||
headers:
|
headers:
|
||||||
x-curry-gull: vinadloo`
|
x-curry-gull: vinadloo`
|
||||||
@@ -230,14 +221,12 @@ headers:
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "seagull", n.FindExtension("x-curry").Value)
|
assert.Equal(t, "seagull", n.FindExtension("x-curry").Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestComponents_Build_HashEmpty(t *testing.T) {
|
func TestComponents_Build_HashEmpty(t *testing.T) {
|
||||||
|
|
||||||
yml := `x-curry: seagull`
|
yml := `x-curry: seagull`
|
||||||
|
|
||||||
var idxNode yaml.Node
|
var idxNode yaml.Node
|
||||||
@@ -249,11 +238,10 @@ func TestComponents_Build_HashEmpty(t *testing.T) {
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(idxNode.Content[0], idx)
|
err = n.Build(context.Background(), idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "seagull", n.FindExtension("x-curry").Value)
|
assert.Equal(t, "seagull", n.FindExtension("x-curry").Value)
|
||||||
assert.Len(t, n.GetExtensions(), 1)
|
assert.Len(t, n.GetExtensions(), 1)
|
||||||
assert.Equal(t, "9cf2c6ab3f9ff7e5231fcb391c8af5c47406711d2ca366533f21a8bb2f67edfe",
|
assert.Equal(t, "9cf2c6ab3f9ff7e5231fcb391c8af5c47406711d2ca366533f21a8bb2f67edfe",
|
||||||
low.GenerateHashString(&n))
|
low.GenerateHashString(&n))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"path/filepath"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
@@ -10,7 +11,6 @@ import (
|
|||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
"github.com/pb33f/libopenapi/datamodel/low/base"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/pb33f/libopenapi/orderedmap"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/pb33f/libopenapi/resolver"
|
|
||||||
"github.com/pb33f/libopenapi/utils"
|
"github.com/pb33f/libopenapi/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,70 +18,97 @@ import (
|
|||||||
//
|
//
|
||||||
// Deprecated: Use CreateDocumentFromConfig instead. This function will be removed in a later version, it
|
// Deprecated: Use CreateDocumentFromConfig instead. This function will be removed in a later version, it
|
||||||
// defaults to allowing file and remote references, and does not support relative file references.
|
// defaults to allowing file and remote references, and does not support relative file references.
|
||||||
func CreateDocument(info *datamodel.SpecInfo) (*Document, []error) {
|
func CreateDocument(info *datamodel.SpecInfo) (*Document, error) {
|
||||||
config := datamodel.DocumentConfiguration{
|
return createDocument(info, datamodel.NewDocumentConfiguration())
|
||||||
AllowFileReferences: true,
|
|
||||||
AllowRemoteReferences: true,
|
|
||||||
}
|
|
||||||
return createDocument(info, &config)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateDocumentFromConfig Create a new document from the provided SpecInfo and DocumentConfiguration pointer.
|
// CreateDocumentFromConfig Create a new document from the provided SpecInfo and DocumentConfiguration pointer.
|
||||||
func CreateDocumentFromConfig(info *datamodel.SpecInfo, config *datamodel.DocumentConfiguration) (*Document, []error) {
|
func CreateDocumentFromConfig(info *datamodel.SpecInfo, config *datamodel.DocumentConfiguration) (*Document, error) {
|
||||||
return createDocument(info, config)
|
return createDocument(info, config)
|
||||||
}
|
}
|
||||||
|
|
||||||
func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfiguration) (*Document, []error) {
|
func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfiguration) (*Document, error) {
|
||||||
_, labelNode, versionNode := utils.FindKeyNodeFull(OpenAPILabel, info.RootNode.Content)
|
_, labelNode, versionNode := utils.FindKeyNodeFull(OpenAPILabel, info.RootNode.Content)
|
||||||
var version low.NodeReference[string]
|
var version low.NodeReference[string]
|
||||||
if versionNode == nil {
|
if versionNode == nil {
|
||||||
return nil, []error{errors.New("no openapi version/tag found, cannot create document")}
|
return nil, errors.New("no openapi version/tag found, cannot create document")
|
||||||
}
|
}
|
||||||
version = low.NodeReference[string]{Value: versionNode.Value, KeyNode: labelNode, ValueNode: versionNode}
|
version = low.NodeReference[string]{Value: versionNode.Value, KeyNode: labelNode, ValueNode: versionNode}
|
||||||
doc := Document{Version: version}
|
doc := Document{Version: version}
|
||||||
|
|
||||||
// get current working directory as a basePath
|
// create an index config and shadow the document configuration.
|
||||||
cwd, _ := os.Getwd()
|
idxConfig := index.CreateClosedAPIIndexConfig()
|
||||||
|
idxConfig.SpecInfo = info
|
||||||
|
idxConfig.IgnoreArrayCircularReferences = config.IgnoreArrayCircularReferences
|
||||||
|
idxConfig.IgnorePolymorphicCircularReferences = config.IgnorePolymorphicCircularReferences
|
||||||
|
idxConfig.AvoidCircularReferenceCheck = true
|
||||||
|
idxConfig.BaseURL = config.BaseURL
|
||||||
|
idxConfig.BasePath = config.BasePath
|
||||||
|
idxConfig.Logger = config.Logger
|
||||||
|
rolodex := index.NewRolodex(idxConfig)
|
||||||
|
rolodex.SetRootNode(info.RootNode)
|
||||||
|
doc.Rolodex = rolodex
|
||||||
|
|
||||||
// If basePath is provided override it
|
// If basePath is provided, add a local filesystem to the rolodex.
|
||||||
if config.BasePath != "" {
|
if idxConfig.BasePath != "" || config.AllowFileReferences {
|
||||||
cwd = config.BasePath
|
var cwd string
|
||||||
|
cwd, _ = filepath.Abs(config.BasePath)
|
||||||
|
// if a supplied local filesystem is provided, add it to the rolodex.
|
||||||
|
if config.LocalFS != nil {
|
||||||
|
rolodex.AddLocalFS(cwd, config.LocalFS)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
// create a local filesystem
|
||||||
|
localFSConf := index.LocalFSConfig{
|
||||||
|
BaseDirectory: cwd,
|
||||||
|
IndexConfig: idxConfig,
|
||||||
|
FileFilters: config.FileFilter,
|
||||||
}
|
}
|
||||||
// build an index
|
|
||||||
idx := index.NewSpecIndexWithConfig(info.RootNode, &index.SpecIndexConfig{
|
|
||||||
BaseURL: config.BaseURL,
|
|
||||||
RemoteURLHandler: config.RemoteURLHandler,
|
|
||||||
BasePath: cwd,
|
|
||||||
AllowFileLookup: config.AllowFileReferences,
|
|
||||||
AllowRemoteLookup: config.AllowRemoteReferences,
|
|
||||||
AvoidBuildIndex: config.AvoidIndexBuild,
|
|
||||||
})
|
|
||||||
doc.Index = idx
|
|
||||||
|
|
||||||
|
fileFS, _ := index.NewLocalFSWithConfig(&localFSConf)
|
||||||
|
idxConfig.AllowFileLookup = true
|
||||||
|
|
||||||
|
// add the filesystem to the rolodex
|
||||||
|
rolodex.AddLocalFS(cwd, fileFS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// if base url is provided, add a remote filesystem to the rolodex.
|
||||||
|
if idxConfig.BaseURL != nil || config.AllowRemoteReferences {
|
||||||
|
|
||||||
|
// create a remote filesystem
|
||||||
|
remoteFS, _ := index.NewRemoteFSWithConfig(idxConfig)
|
||||||
|
if config.RemoteURLHandler != nil {
|
||||||
|
remoteFS.RemoteHandlerFunc = config.RemoteURLHandler
|
||||||
|
}
|
||||||
|
idxConfig.AllowRemoteLookup = true
|
||||||
|
|
||||||
|
// add to the rolodex
|
||||||
|
u := "default"
|
||||||
|
if config.BaseURL != nil {
|
||||||
|
u = config.BaseURL.String()
|
||||||
|
}
|
||||||
|
rolodex.AddRemoteFS(u, remoteFS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// index the rolodex
|
||||||
var errs []error
|
var errs []error
|
||||||
|
|
||||||
errs = idx.GetReferenceIndexErrors()
|
// index all the things.
|
||||||
|
_ = rolodex.IndexTheRolodex()
|
||||||
|
|
||||||
// create resolver and check for circular references.
|
// check for circular references
|
||||||
resolve := resolver.NewResolver(idx)
|
if !config.SkipCircularReferenceCheck {
|
||||||
|
rolodex.CheckForCircularReferences()
|
||||||
// if configured, ignore circular references in arrays and polymorphic schemas
|
|
||||||
if config.IgnoreArrayCircularReferences {
|
|
||||||
resolve.IgnoreArrayCircularReferences()
|
|
||||||
}
|
|
||||||
if config.IgnorePolymorphicCircularReferences {
|
|
||||||
resolve.IgnorePolymorphicCircularReferences()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// check for circular references.
|
// extract errors
|
||||||
resolvingErrors := resolve.CheckForCircularReferences()
|
roloErrs := rolodex.GetCaughtErrors()
|
||||||
|
if roloErrs != nil {
|
||||||
if len(resolvingErrors) > 0 {
|
errs = append(errs, roloErrs...)
|
||||||
for r := range resolvingErrors {
|
|
||||||
errs = append(errs, resolvingErrors[r])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set root index.
|
||||||
|
doc.Index = rolodex.GetRootIndex()
|
||||||
var wg sync.WaitGroup
|
var wg sync.WaitGroup
|
||||||
|
|
||||||
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
doc.Extensions = low.ExtractExtensions(info.RootNode.Content[0])
|
||||||
@@ -94,17 +121,17 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
runExtraction := func(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
runExtraction := func(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex,
|
||||||
runFunc func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
runFunc func(ctx context.Context, i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error,
|
||||||
ers *[]error,
|
ers *[]error,
|
||||||
wg *sync.WaitGroup,
|
wg *sync.WaitGroup,
|
||||||
) {
|
) {
|
||||||
if er := runFunc(info, doc, idx); er != nil {
|
if er := runFunc(ctx, info, doc, idx); er != nil {
|
||||||
*ers = append(*ers, er)
|
*ers = append(*ers, er)
|
||||||
}
|
}
|
||||||
wg.Done()
|
wg.Done()
|
||||||
}
|
}
|
||||||
extractionFuncs := []func(i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
extractionFuncs := []func(ctx context.Context, i *datamodel.SpecInfo, d *Document, idx *index.SpecIndex) error{
|
||||||
extractInfo,
|
extractInfo,
|
||||||
extractServers,
|
extractServers,
|
||||||
extractTags,
|
extractTags,
|
||||||
@@ -115,28 +142,30 @@ func createDocument(info *datamodel.SpecInfo, config *datamodel.DocumentConfigur
|
|||||||
extractWebhooks,
|
extractWebhooks,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx := context.Background()
|
||||||
|
|
||||||
wg.Add(len(extractionFuncs))
|
wg.Add(len(extractionFuncs))
|
||||||
for _, f := range extractionFuncs {
|
for _, f := range extractionFuncs {
|
||||||
go runExtraction(info, &doc, idx, f, &errs, &wg)
|
go runExtraction(ctx, info, &doc, rolodex.GetRootIndex(), f, &errs, &wg)
|
||||||
}
|
}
|
||||||
wg.Wait()
|
wg.Wait()
|
||||||
return &doc, errs
|
return &doc, errors.Join(errs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractInfo(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractInfo(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFullTop(base.InfoLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFullTop(base.InfoLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := base.Info{}
|
ir := base.Info{}
|
||||||
_ = low.BuildModel(vn, &ir)
|
_ = low.BuildModel(vn, &ir)
|
||||||
_ = ir.Build(ln, vn, idx)
|
_ = ir.Build(ctx, ln, vn, idx)
|
||||||
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
nr := low.NodeReference[*base.Info]{Value: &ir, ValueNode: vn, KeyNode: ln}
|
||||||
doc.Info = nr
|
doc.Info = nr
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractSecurity(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](SecurityLabel, info.RootNode.Content[0], idx)
|
sec, ln, vn, err := low.ExtractArray[*base.SecurityRequirement](ctx, SecurityLabel, info.RootNode.Content[0], idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -150,8 +179,8 @@ func extractSecurity(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInd
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractExternalDocs(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
extDocs, dErr := low.ExtractObject[*base.ExternalDoc](ctx, base.ExternalDocsLabel, info.RootNode.Content[0], idx)
|
||||||
if dErr != nil {
|
if dErr != nil {
|
||||||
return dErr
|
return dErr
|
||||||
}
|
}
|
||||||
@@ -159,12 +188,12 @@ func extractExternalDocs(info *datamodel.SpecInfo, doc *Document, idx *index.Spe
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractComponents(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFullTop(ComponentsLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFullTop(ComponentsLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := Components{}
|
ir := Components{}
|
||||||
_ = low.BuildModel(vn, &ir)
|
_ = low.BuildModel(vn, &ir)
|
||||||
err := ir.Build(vn, idx)
|
err := ir.Build(ctx, vn, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -174,7 +203,7 @@ func extractComponents(info *datamodel.SpecInfo, doc *Document, idx *index.SpecI
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractServers(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFull(ServersLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if utils.IsNodeArray(vn) {
|
if utils.IsNodeArray(vn) {
|
||||||
@@ -183,7 +212,7 @@ func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInde
|
|||||||
if utils.IsNodeMap(srvN) {
|
if utils.IsNodeMap(srvN) {
|
||||||
srvr := Server{}
|
srvr := Server{}
|
||||||
_ = low.BuildModel(srvN, &srvr)
|
_ = low.BuildModel(srvN, &srvr)
|
||||||
_ = srvr.Build(ln, srvN, idx)
|
_ = srvr.Build(ctx, ln, srvN, idx)
|
||||||
servers = append(servers, low.ValueReference[*Server]{
|
servers = append(servers, low.ValueReference[*Server]{
|
||||||
Value: &srvr,
|
Value: &srvr,
|
||||||
ValueNode: srvN,
|
ValueNode: srvN,
|
||||||
@@ -200,7 +229,7 @@ func extractServers(info *datamodel.SpecInfo, doc *Document, idx *index.SpecInde
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractTags(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFull(base.TagsLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
if utils.IsNodeArray(vn) {
|
if utils.IsNodeArray(vn) {
|
||||||
@@ -209,7 +238,7 @@ func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
|||||||
if utils.IsNodeMap(tagN) {
|
if utils.IsNodeMap(tagN) {
|
||||||
tag := base.Tag{}
|
tag := base.Tag{}
|
||||||
_ = low.BuildModel(tagN, &tag)
|
_ = low.BuildModel(tagN, &tag)
|
||||||
if err := tag.Build(ln, tagN, idx); err != nil {
|
if err := tag.Build(ctx, ln, tagN, idx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
tags = append(tags, low.ValueReference[*base.Tag]{
|
tags = append(tags, low.ValueReference[*base.Tag]{
|
||||||
@@ -228,11 +257,11 @@ func extractTags(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractPaths(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content[0].Content)
|
_, ln, vn := utils.FindKeyNodeFull(PathsLabel, info.RootNode.Content[0].Content)
|
||||||
if vn != nil {
|
if vn != nil {
|
||||||
ir := Paths{}
|
ir := Paths{}
|
||||||
err := ir.Build(ln, vn, idx)
|
err := ir.Build(ctx, ln, vn, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -242,8 +271,8 @@ func extractPaths(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractWebhooks(info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
func extractWebhooks(ctx context.Context, info *datamodel.SpecInfo, doc *Document, idx *index.SpecIndex) error {
|
||||||
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](WebhooksLabel, info.RootNode, idx)
|
hooks, hooksL, hooksN, eErr := low.ExtractMap[*PathItem](ctx, WebhooksLabel, info.RootNode, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,15 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/pb33f/libopenapi/index"
|
||||||
|
"github.com/pb33f/libopenapi/utils"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low/base"
|
|
||||||
"github.com/pb33f/libopenapi/orderedmap"
|
"github.com/pb33f/libopenapi/orderedmap"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
)
|
)
|
||||||
@@ -19,9 +23,9 @@ func initTest() {
|
|||||||
}
|
}
|
||||||
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
var err []error
|
var err error
|
||||||
// deprecated function test.
|
// deprecated function test.
|
||||||
doc, err = CreateDocument(info)
|
doc, err = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("broken something")
|
panic("broken something")
|
||||||
}
|
}
|
||||||
@@ -31,10 +35,7 @@ func BenchmarkCreateDocument(b *testing.B) {
|
|||||||
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
data, _ := os.ReadFile("../../../test_specs/burgershop.openapi.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
doc, _ = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
doc, _ = CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,47 +43,145 @@ func BenchmarkCreateDocument_Circular(b *testing.B) {
|
|||||||
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err := CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
AllowFileReferences: false,
|
if err == nil {
|
||||||
AllowRemoteReferences: false,
|
panic("this should error, it has circular references")
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic("this should not error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func BenchmarkCreateDocument_k8s(b *testing.B) {
|
|
||||||
|
|
||||||
data, _ := os.ReadFile("../../../test_specs/k8s.json")
|
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
|
|
||||||
_, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic("this should not error")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularReferenceError(t *testing.T) {
|
func TestCircularReferenceError(t *testing.T) {
|
||||||
|
|
||||||
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
data, _ := os.ReadFile("../../../test_specs/circular-tests.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
circDoc, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
circDoc, err := CreateDocumentFromConfig(info, datamodel.NewDocumentConfiguration())
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
assert.NotNil(t, circDoc)
|
assert.NotNil(t, circDoc)
|
||||||
assert.Len(t, err, 3)
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = "../../../test_specs"
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem_ProvideNonRolodexFS(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
baseDir := "../../../test_specs"
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = baseDir
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
cf.LocalFS = os.DirFS(baseDir)
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem_ProvideRolodexFS(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
baseDir := "../../../test_specs"
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = baseDir
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
|
||||||
|
localFS, lErr := index.NewLocalFSWithConfig(&index.LocalFSConfig{
|
||||||
|
BaseDirectory: baseDir,
|
||||||
|
DirFS: os.DirFS(baseDir),
|
||||||
|
FileFilters: cf.FileFilter,
|
||||||
|
})
|
||||||
|
cf.LocalFS = localFS
|
||||||
|
|
||||||
|
assert.NoError(t, lErr)
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexLocalFileSystem_BadPath(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.BasePath = "/NOWHERE"
|
||||||
|
cf.FileFilter = []string{"first.yaml", "second.yaml", "third.yaml"}
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.Logger = slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
|
Level: slog.LevelDebug,
|
||||||
|
}))
|
||||||
|
|
||||||
|
baseUrl := "https://raw.githubusercontent.com/pb33f/libopenapi/main/test_specs"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_BadBase(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
|
||||||
|
baseUrl := "https://no-no-this-will-not-work-it-just-will-not-get-the-job-done-mate.com"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_CustomRemote_NoBaseURL(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.RemoteFS, _ = index.NewRemoteFSWithConfig(&index.SpecIndexConfig{})
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRolodexRemoteFileSystem_CustomHttpHandler(t *testing.T) {
|
||||||
|
data, _ := os.ReadFile("../../../test_specs/first.yaml")
|
||||||
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
|
cf := datamodel.NewDocumentConfiguration()
|
||||||
|
cf.RemoteURLHandler = http.Get
|
||||||
|
baseUrl := "https://no-no-this-will-not-work-it-just-will-not-get-the-job-done-mate.com"
|
||||||
|
u, _ := url.Parse(baseUrl)
|
||||||
|
cf.BaseURL = u
|
||||||
|
|
||||||
|
pizza := func(url string) (resp *http.Response, err error) {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
cf.RemoteURLHandler = pizza
|
||||||
|
lDoc, err := CreateDocumentFromConfig(info, cf)
|
||||||
|
assert.NotNil(t, lDoc)
|
||||||
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularReference_IgnoreArray(t *testing.T) {
|
func TestCircularReference_IgnoreArray(t *testing.T) {
|
||||||
|
|
||||||
spec := `openapi: 3.1.0
|
spec := `openapi: 3.1.0
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
@@ -102,16 +201,13 @@ components:
|
|||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(spec))
|
info, _ := datamodel.ExtractSpecInfo([]byte(spec))
|
||||||
circDoc, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
circDoc, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
IgnoreArrayCircularReferences: true,
|
IgnoreArrayCircularReferences: true,
|
||||||
})
|
})
|
||||||
assert.NotNil(t, circDoc)
|
assert.NotNil(t, circDoc)
|
||||||
assert.Len(t, err, 0)
|
assert.Len(t, utils.UnwrapErrors(err), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCircularReference_IgnorePoly(t *testing.T) {
|
func TestCircularReference_IgnorePoly(t *testing.T) {
|
||||||
|
|
||||||
spec := `openapi: 3.1.0
|
spec := `openapi: 3.1.0
|
||||||
components:
|
components:
|
||||||
schemas:
|
schemas:
|
||||||
@@ -131,12 +227,10 @@ components:
|
|||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(spec))
|
info, _ := datamodel.ExtractSpecInfo([]byte(spec))
|
||||||
circDoc, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
circDoc, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
IgnorePolymorphicCircularReferences: true,
|
IgnorePolymorphicCircularReferences: true,
|
||||||
})
|
})
|
||||||
assert.NotNil(t, circDoc)
|
assert.NotNil(t, circDoc)
|
||||||
assert.Len(t, err, 0)
|
assert.Len(t, utils.UnwrapErrors(err), 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
||||||
@@ -144,10 +238,7 @@ func BenchmarkCreateDocument_Stripe(b *testing.B) {
|
|||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("this should not error")
|
panic("this should not error")
|
||||||
}
|
}
|
||||||
@@ -158,10 +249,7 @@ func BenchmarkCreateDocument_Petstore(b *testing.B) {
|
|||||||
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
data, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
_, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic("this should not error")
|
panic("this should not error")
|
||||||
}
|
}
|
||||||
@@ -169,15 +257,10 @@ func BenchmarkCreateDocument_Petstore(b *testing.B) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocumentStripe(t *testing.T) {
|
func TestCreateDocumentStripe(t *testing.T) {
|
||||||
|
|
||||||
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
data, _ := os.ReadFile("../../../test_specs/stripe.yaml")
|
||||||
info, _ := datamodel.ExtractSpecInfo(data)
|
info, _ := datamodel.ExtractSpecInfo(data)
|
||||||
d, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
d, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Len(t, utils.UnwrapErrors(err), 3)
|
||||||
AllowRemoteReferences: false,
|
|
||||||
BasePath: "/here",
|
|
||||||
})
|
|
||||||
assert.Len(t, err, 3)
|
|
||||||
|
|
||||||
assert.Equal(t, "3.0.0", d.Version.Value)
|
assert.Equal(t, "3.0.0", d.Version.Value)
|
||||||
assert.Equal(t, "Stripe API", d.Info.Value.Title.Value)
|
assert.Equal(t, "Stripe API", d.Info.Value.Title.Value)
|
||||||
@@ -234,16 +317,14 @@ func TestCreateDocument_WebHooks(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
func TestCreateDocument_WebHooks_Error(t *testing.T) {
|
||||||
yml := `webhooks:
|
yml := `openapi: 3.0
|
||||||
|
webhooks:
|
||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Len(t, utils.UnwrapErrors(err), 1)
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
assert.Len(t, err, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Servers(t *testing.T) {
|
func TestCreateDocument_Servers(t *testing.T) {
|
||||||
@@ -304,7 +385,6 @@ func TestCreateDocument_Tags(t *testing.T) {
|
|||||||
// this is why we will need a higher level API to this model, this looks cool and all, but dude.
|
// this is why we will need a higher level API to this model, this looks cool and all, but dude.
|
||||||
assert.Equal(t, "now?", extension.Value.(map[string]interface{})["ok"].([]interface{})[0].(map[string]interface{})["what"])
|
assert.Equal(t, "now?", extension.Value.(map[string]interface{})["ok"].([]interface{})[0].(map[string]interface{})["what"])
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// tag2
|
/// tag2
|
||||||
@@ -314,7 +394,6 @@ func TestCreateDocument_Tags(t *testing.T) {
|
|||||||
assert.Equal(t, "https://pb33f.io", doc.Tags.Value[1].Value.ExternalDocs.Value.URL.Value)
|
assert.Equal(t, "https://pb33f.io", doc.Tags.Value[1].Value.ExternalDocs.Value.URL.Value)
|
||||||
assert.NotEmpty(t, doc.Tags.Value[1].Value.ExternalDocs.Value.URL.Value)
|
assert.NotEmpty(t, doc.Tags.Value[1].Value.ExternalDocs.Value.URL.Value)
|
||||||
assert.Len(t, doc.Tags.Value[1].Value.Extensions, 0)
|
assert.Len(t, doc.Tags.Value[1].Value.Extensions, 0)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Paths(t *testing.T) {
|
func TestCreateDocument_Paths(t *testing.T) {
|
||||||
@@ -439,7 +518,6 @@ func TestCreateDocument_Paths(t *testing.T) {
|
|||||||
assert.NotNil(t, servers)
|
assert.NotNil(t, servers)
|
||||||
assert.Len(t, servers, 1)
|
assert.Len(t, servers, 1)
|
||||||
assert.Equal(t, "https://pb33f.io", servers[0].Value.URL.Value)
|
assert.Equal(t, "https://pb33f.io", servers[0].Value.URL.Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Components_Schemas(t *testing.T) {
|
func TestCreateDocument_Components_Schemas(t *testing.T) {
|
||||||
@@ -465,7 +543,6 @@ func TestCreateDocument_Components_Schemas(t *testing.T) {
|
|||||||
p := fries.Value.Schema().FindProperty("favoriteDrink")
|
p := fries.Value.Schema().FindProperty("favoriteDrink")
|
||||||
assert.Equal(t, "a frosty cold beverage can be coke or sprite",
|
assert.Equal(t, "a frosty cold beverage can be coke or sprite",
|
||||||
p.Value.Schema().Description.Value)
|
p.Value.Schema().Description.Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Components_SecuritySchemes(t *testing.T) {
|
func TestCreateDocument_Components_SecuritySchemes(t *testing.T) {
|
||||||
@@ -494,7 +571,6 @@ func TestCreateDocument_Components_SecuritySchemes(t *testing.T) {
|
|||||||
readScope = oAuth.Flows.Value.AuthorizationCode.Value.FindScope("write:burgers")
|
readScope = oAuth.Flows.Value.AuthorizationCode.Value.FindScope("write:burgers")
|
||||||
assert.NotNil(t, readScope)
|
assert.NotNil(t, readScope)
|
||||||
assert.Equal(t, "modify burgers and stuff", readScope.Value)
|
assert.Equal(t, "modify burgers and stuff", readScope.Value)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Components_Responses(t *testing.T) {
|
func TestCreateDocument_Components_Responses(t *testing.T) {
|
||||||
@@ -507,7 +583,6 @@ func TestCreateDocument_Components_Responses(t *testing.T) {
|
|||||||
assert.NotNil(t, dressingResponse.Value)
|
assert.NotNil(t, dressingResponse.Value)
|
||||||
assert.Equal(t, "all the dressings for a burger.", dressingResponse.Value.Description.Value)
|
assert.Equal(t, "all the dressings for a burger.", dressingResponse.Value.Description.Value)
|
||||||
assert.Len(t, dressingResponse.Value.Content.Value, 1)
|
assert.Len(t, dressingResponse.Value.Content.Value, 1)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Components_Examples(t *testing.T) {
|
func TestCreateDocument_Components_Examples(t *testing.T) {
|
||||||
@@ -594,7 +669,6 @@ func TestCreateDocument_Component_Discriminator(t *testing.T) {
|
|||||||
assert.Nil(t, dsc.FindMappingValue("don't exist"))
|
assert.Nil(t, dsc.FindMappingValue("don't exist"))
|
||||||
assert.NotNil(t, doc.GetExternalDocs())
|
assert.NotNil(t, doc.GetExternalDocs())
|
||||||
assert.Nil(t, doc.FindSecurityRequirement("scooby doo"))
|
assert.Nil(t, doc.FindSecurityRequirement("scooby doo"))
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_CheckAdditionalProperties_Schema(t *testing.T) {
|
func TestCreateDocument_CheckAdditionalProperties_Schema(t *testing.T) {
|
||||||
@@ -602,11 +676,8 @@ func TestCreateDocument_CheckAdditionalProperties_Schema(t *testing.T) {
|
|||||||
components := doc.Components.Value
|
components := doc.Components.Value
|
||||||
d := components.FindSchema("Dressing")
|
d := components.FindSchema("Dressing")
|
||||||
assert.NotNil(t, d.Value.Schema().AdditionalProperties.Value)
|
assert.NotNil(t, d.Value.Schema().AdditionalProperties.Value)
|
||||||
if n, ok := d.Value.Schema().AdditionalProperties.Value.(*base.SchemaProxy); ok {
|
|
||||||
assert.Equal(t, "something in here.", n.Schema().Description.Value)
|
assert.True(t, d.Value.Schema().AdditionalProperties.Value.IsA(), "should be a schema")
|
||||||
} else {
|
|
||||||
assert.Fail(t, "should be a schema")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_CheckAdditionalProperties_Bool(t *testing.T) {
|
func TestCreateDocument_CheckAdditionalProperties_Bool(t *testing.T) {
|
||||||
@@ -614,7 +685,7 @@ func TestCreateDocument_CheckAdditionalProperties_Bool(t *testing.T) {
|
|||||||
components := doc.Components.Value
|
components := doc.Components.Value
|
||||||
d := components.FindSchema("Drink")
|
d := components.FindSchema("Drink")
|
||||||
assert.NotNil(t, d.Value.Schema().AdditionalProperties.Value)
|
assert.NotNil(t, d.Value.Schema().AdditionalProperties.Value)
|
||||||
assert.True(t, d.Value.Schema().AdditionalProperties.Value.(bool))
|
assert.True(t, d.Value.Schema().AdditionalProperties.Value.B)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Components_Error(t *testing.T) {
|
func TestCreateDocument_Components_Error(t *testing.T) {
|
||||||
@@ -627,12 +698,9 @@ components:
|
|||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
doc, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.NoError(t, err)
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
assert.Len(t, err, 0)
|
|
||||||
|
|
||||||
ob := doc.Components.Value.FindSchema("bork").Value
|
ob := doc.Components.Value.FindSchema("bork").Value
|
||||||
ob.Schema()
|
ob.Schema()
|
||||||
@@ -646,12 +714,10 @@ webhooks:
|
|||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
doc, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
doc, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Equal(t, "flat map build failed: reference cannot be found: reference at line 4, column 5 is empty, it cannot be resolved",
|
||||||
AllowRemoteReferences: false,
|
err.Error())
|
||||||
})
|
|
||||||
assert.Len(t, err, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Components_Error_Extract(t *testing.T) {
|
func TestCreateDocument_Components_Error_Extract(t *testing.T) {
|
||||||
@@ -662,13 +728,9 @@ components:
|
|||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Equal(t, "reference at line 5, column 7 is empty, it cannot be resolved", err.Error())
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
assert.Len(t, err, 1)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Paths_Errors(t *testing.T) {
|
func TestCreateDocument_Paths_Errors(t *testing.T) {
|
||||||
@@ -678,12 +740,10 @@ paths:
|
|||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Equal(t,
|
||||||
AllowRemoteReferences: false,
|
"path item build failed: cannot find reference: at line 4, col 10", err.Error())
|
||||||
})
|
|
||||||
assert.Len(t, err, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Tags_Errors(t *testing.T) {
|
func TestCreateDocument_Tags_Errors(t *testing.T) {
|
||||||
@@ -692,12 +752,10 @@ tags:
|
|||||||
- $ref: #bork`
|
- $ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Equal(t,
|
||||||
AllowRemoteReferences: false,
|
"object extraction failed: reference at line 3, column 5 is empty, it cannot be resolved", err.Error())
|
||||||
})
|
|
||||||
assert.Len(t, err, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_Security_Error(t *testing.T) {
|
func TestCreateDocument_Security_Error(t *testing.T) {
|
||||||
@@ -706,12 +764,11 @@ security:
|
|||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Equal(t,
|
||||||
AllowRemoteReferences: false,
|
"array build failed: reference cannot be found: reference at line 3, column 3 is empty, it cannot be resolved",
|
||||||
})
|
err.Error())
|
||||||
assert.Len(t, err, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_ExternalDoc_Error(t *testing.T) {
|
func TestCreateDocument_ExternalDoc_Error(t *testing.T) {
|
||||||
@@ -720,12 +777,9 @@ externalDocs:
|
|||||||
$ref: #bork`
|
$ref: #bork`
|
||||||
|
|
||||||
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
var err []error
|
var err error
|
||||||
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
assert.Equal(t, "object extraction failed: reference at line 3, column 3 is empty, it cannot be resolved", err.Error())
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
assert.Len(t, err, 1)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateDocument_YamlAnchor(t *testing.T) {
|
func TestCreateDocument_YamlAnchor(t *testing.T) {
|
||||||
@@ -736,16 +790,10 @@ func TestCreateDocument_YamlAnchor(t *testing.T) {
|
|||||||
info, _ := datamodel.ExtractSpecInfo(anchorDocument)
|
info, _ := datamodel.ExtractSpecInfo(anchorDocument)
|
||||||
|
|
||||||
// build low-level document model
|
// build low-level document model
|
||||||
document, errors := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
document, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
// if something went wrong, a slice of errors is returned
|
if err != nil {
|
||||||
if len(errors) > 0 {
|
fmt.Printf("error: %s\n", err.Error())
|
||||||
for i := range errors {
|
|
||||||
fmt.Printf("error: %s\n", errors[i].Error())
|
|
||||||
}
|
|
||||||
panic("cannot build document")
|
panic("cannot build document")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -777,8 +825,19 @@ func TestCreateDocument_YamlAnchor(t *testing.T) {
|
|||||||
assert.NotNil(t, jsonGet)
|
assert.NotNil(t, jsonGet)
|
||||||
|
|
||||||
// Should this work? It doesn't
|
// Should this work? It doesn't
|
||||||
//postJsonType := examplePath.GetValue().Post.GetValue().RequestBody.GetValue().FindContent("application/json")
|
// update from quobix 10/14/2023: It does now!
|
||||||
//assert.NotNil(t, postJsonType)
|
postJsonType := examplePath.GetValue().Post.GetValue().RequestBody.GetValue().FindContent("application/json")
|
||||||
|
assert.NotNil(t, postJsonType)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateDocument_NotOpenAPI_EnforcedDocCheck(t *testing.T) {
|
||||||
|
yml := `notadoc: no`
|
||||||
|
|
||||||
|
info, _ := datamodel.ExtractSpecInfo([]byte(yml))
|
||||||
|
var err error
|
||||||
|
_, err = CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
|
assert.Equal(t,
|
||||||
|
"no openapi version/tag found, cannot create document", err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExampleCreateDocument() {
|
func ExampleCreateDocument() {
|
||||||
@@ -791,16 +850,10 @@ func ExampleCreateDocument() {
|
|||||||
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
||||||
|
|
||||||
// build low-level document model
|
// build low-level document model
|
||||||
document, errors := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{
|
document, err := CreateDocumentFromConfig(info, &datamodel.DocumentConfiguration{})
|
||||||
AllowFileReferences: false,
|
|
||||||
AllowRemoteReferences: false,
|
|
||||||
})
|
|
||||||
|
|
||||||
// if something went wrong, a slice of errors is returned
|
if err != nil {
|
||||||
if len(errors) > 0 {
|
fmt.Printf("error: %s\n", err.Error())
|
||||||
for i := range errors {
|
|
||||||
fmt.Printf("error: %s\n", errors[i].Error())
|
|
||||||
}
|
|
||||||
panic("cannot build document")
|
panic("cannot build document")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -83,6 +83,9 @@ type Document struct {
|
|||||||
//
|
//
|
||||||
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
|
||||||
Index *index.SpecIndex
|
Index *index.SpecIndex
|
||||||
|
|
||||||
|
// Rolodex is a reference to the rolodex used when creating this document.
|
||||||
|
Rolodex *index.Rolodex
|
||||||
}
|
}
|
||||||
|
|
||||||
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
// FindSecurityRequirement will attempt to locate a security requirement string from a supplied name.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -61,11 +62,11 @@ func (en *Encoding) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract all Header objects from supplied node.
|
// Build will extract all Header objects from supplied node.
|
||||||
func (en *Encoding) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (en *Encoding) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
en.Reference = new(low.Reference)
|
en.Reference = new(low.Reference)
|
||||||
headers, hL, hN, err := low.ExtractMap[*Header](HeadersLabel, root, idx)
|
headers, hL, hN, err := low.ExtractMap[*Header](ctx, HeadersLabel, root, idx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"github.com/pb33f/libopenapi/datamodel/low"
|
"github.com/pb33f/libopenapi/datamodel/low"
|
||||||
"github.com/pb33f/libopenapi/index"
|
"github.com/pb33f/libopenapi/index"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -31,7 +32,7 @@ explode: true`
|
|||||||
err := low.BuildModel(idxNode.Content[0], &n)
|
err := low.BuildModel(idxNode.Content[0], &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Equal(t, "hot/cakes", n.ContentType.Value)
|
assert.Equal(t, "hot/cakes", n.ContentType.Value)
|
||||||
assert.Equal(t, true, n.AllowReserved.Value)
|
assert.Equal(t, true, n.AllowReserved.Value)
|
||||||
@@ -59,7 +60,7 @@ headers:
|
|||||||
err := low.BuildModel(&idxNode, &n)
|
err := low.BuildModel(&idxNode, &n)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
err = n.Build(nil, idxNode.Content[0], idx)
|
err = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,7 +80,7 @@ allowReserved: true`
|
|||||||
|
|
||||||
var n Encoding
|
var n Encoding
|
||||||
_ = low.BuildModel(idxNode.Content[0], &n)
|
_ = low.BuildModel(idxNode.Content[0], &n)
|
||||||
_ = n.Build(nil, idxNode.Content[0], idx)
|
_ = n.Build(context.Background(), nil, idxNode.Content[0], idx)
|
||||||
|
|
||||||
yml2 := `explode: true
|
yml2 := `explode: true
|
||||||
contentType: application/waffle
|
contentType: application/waffle
|
||||||
@@ -96,7 +97,7 @@ style: post modern
|
|||||||
|
|
||||||
var n2 Encoding
|
var n2 Encoding
|
||||||
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
_ = low.BuildModel(idxNode2.Content[0], &n2)
|
||||||
_ = n2.Build(nil, idxNode2.Content[0], idx2)
|
_ = n2.Build(context.Background(), nil, idxNode2.Content[0], idx2)
|
||||||
|
|
||||||
// hash
|
// hash
|
||||||
assert.Equal(t, n.Hash(), n2.Hash())
|
assert.Equal(t, n.Hash(), n2.Hash())
|
||||||
|
|||||||
@@ -5,8 +5,9 @@ package v3
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/pb33f/libopenapi/datamodel"
|
"github.com/pb33f/libopenapi/datamodel"
|
||||||
"io/ioutil"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// How to create a low-level OpenAPI 3+ Document from an OpenAPI specification
|
// How to create a low-level OpenAPI 3+ Document from an OpenAPI specification
|
||||||
@@ -14,19 +15,17 @@ func Example_createLowLevelOpenAPIDocument() {
|
|||||||
// How to create a low-level OpenAPI 3 Document
|
// How to create a low-level OpenAPI 3 Document
|
||||||
|
|
||||||
// load petstore into bytes
|
// load petstore into bytes
|
||||||
petstoreBytes, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
|
petstoreBytes, _ := os.ReadFile("../../../test_specs/petstorev3.json")
|
||||||
|
|
||||||
// read in specification
|
// read in specification
|
||||||
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
|
||||||
|
|
||||||
// build low-level document model
|
// build low-level document model
|
||||||
document, errors := CreateDocument(info)
|
document, errs := CreateDocument(info)
|
||||||
|
|
||||||
// if something went wrong, a slice of errors is returned
|
// if something went wrong, a slice of errors is returned
|
||||||
if len(errors) > 0 {
|
if errs != nil {
|
||||||
for i := range errors {
|
fmt.Printf("error: %s\n", errs.Error())
|
||||||
fmt.Printf("error: %s\n", errors[i].Error())
|
|
||||||
}
|
|
||||||
panic("cannot build document")
|
panic("cannot build document")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
package v3
|
package v3
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"fmt"
|
"fmt"
|
||||||
"sort"
|
"sort"
|
||||||
@@ -97,7 +98,7 @@ func (h *Header) Hash() [32]byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Build will extract extensions, examples, schema and content/media types from node.
|
// Build will extract extensions, examples, schema and content/media types from node.
|
||||||
func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
func (h *Header) Build(ctx context.Context, _, root *yaml.Node, idx *index.SpecIndex) error {
|
||||||
root = utils.NodeAlias(root)
|
root = utils.NodeAlias(root)
|
||||||
utils.CheckForMergeNodes(root)
|
utils.CheckForMergeNodes(root)
|
||||||
h.Reference = new(low.Reference)
|
h.Reference = new(low.Reference)
|
||||||
@@ -110,7 +111,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle examples if set.
|
// handle examples if set.
|
||||||
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](base.ExamplesLabel, root, idx)
|
exps, expsL, expsN, eErr := low.ExtractMap[*base.Example](ctx, base.ExamplesLabel, root, idx)
|
||||||
if eErr != nil {
|
if eErr != nil {
|
||||||
return eErr
|
return eErr
|
||||||
}
|
}
|
||||||
@@ -123,7 +124,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle schema
|
// handle schema
|
||||||
sch, sErr := base.ExtractSchema(root, idx)
|
sch, sErr := base.ExtractSchema(ctx, root, idx)
|
||||||
if sErr != nil {
|
if sErr != nil {
|
||||||
return sErr
|
return sErr
|
||||||
}
|
}
|
||||||
@@ -132,7 +133,7 @@ func (h *Header) Build(_, root *yaml.Node, idx *index.SpecIndex) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// handle content, if set.
|
// handle content, if set.
|
||||||
con, cL, cN, cErr := low.ExtractMap[*MediaType](ContentLabel, root, idx)
|
con, cL, cN, cErr := low.ExtractMap[*MediaType](ctx, ContentLabel, root, idx)
|
||||||
if cErr != nil {
|
if cErr != nil {
|
||||||
return cErr
|
return cErr
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user