mirror of
https://github.com/LukeHagar/libopenapi.git
synced 2025-12-06 12:37:49 +00:00
whacking the shit out of exploded use-cases
Before everything worked, but was completely accurate, now everything works and everything is absolute and can be resolved. Phew, what a mission! Signed-off-by: quobix <dave@quobix.com>
This commit is contained in:
@@ -54,6 +54,10 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
definitionPath = fmt.Sprintf("#/%s", strings.Join(loc, "/"))
|
||||
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, strings.Join(loc, "/"))
|
||||
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
|
||||
} else {
|
||||
definitionPath = fmt.Sprintf("#/%s", n.Value)
|
||||
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, n.Value)
|
||||
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
|
||||
}
|
||||
ref := &Reference{
|
||||
FullDefinition: fullDefinitionPath,
|
||||
@@ -105,7 +109,12 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
definitionPath = fmt.Sprintf("#/%s", strings.Join(loc, "/"))
|
||||
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, strings.Join(loc, "/"))
|
||||
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
|
||||
} else {
|
||||
definitionPath = fmt.Sprintf("#/%s", n.Value)
|
||||
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, n.Value)
|
||||
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
|
||||
}
|
||||
|
||||
ref := &Reference{
|
||||
FullDefinition: fullDefinitionPath,
|
||||
Definition: definitionPath,
|
||||
@@ -145,7 +154,12 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
definitionPath = fmt.Sprintf("#/%s", strings.Join(loc, "/"))
|
||||
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, strings.Join(loc, "/"))
|
||||
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
|
||||
} else {
|
||||
definitionPath = fmt.Sprintf("#/%s", n.Value)
|
||||
fullDefinitionPath = fmt.Sprintf("%s#/%s", index.specAbsolutePath, n.Value)
|
||||
_, jsonPath = utils.ConvertComponentIdIntoFriendlyPathSearch(definitionPath)
|
||||
}
|
||||
|
||||
ref := &Reference{
|
||||
FullDefinition: fullDefinitionPath,
|
||||
Definition: definitionPath,
|
||||
@@ -407,6 +421,7 @@ func (index *SpecIndex) ExtractRefs(node, parent *yaml.Node, seenPath []string,
|
||||
//} else {
|
||||
// index.allRefs[value] = ref
|
||||
//}
|
||||
|
||||
index.allRefs[fullDefinitionPath] = ref
|
||||
found = append(found, ref)
|
||||
}
|
||||
@@ -597,13 +612,13 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
||||
if located != nil {
|
||||
index.refLock.Lock()
|
||||
// have we already mapped this?
|
||||
if index.allMappedRefs[ref.Definition] == nil {
|
||||
if index.allMappedRefs[ref.FullDefinition] == nil {
|
||||
found = append(found, located)
|
||||
if located.FullDefinition != ref.FullDefinition {
|
||||
located.FullDefinition = ref.FullDefinition
|
||||
}
|
||||
|
||||
index.allMappedRefs[ref.Definition] = located
|
||||
index.allMappedRefs[ref.FullDefinition] = located
|
||||
rm := &ReferenceMapped{
|
||||
Reference: located,
|
||||
Definition: ref.Definition,
|
||||
@@ -612,7 +627,7 @@ func (index *SpecIndex) ExtractComponentsFromRefs(refs []*Reference) []*Referenc
|
||||
sequence[refIndex] = rm
|
||||
} else {
|
||||
// it exists, but is it a component with the same ID?
|
||||
d := index.allMappedRefs[ref.Definition]
|
||||
d := index.allMappedRefs[ref.FullDefinition]
|
||||
|
||||
// if the full definition matches, we're good and can skip this.
|
||||
if d.FullDefinition != ref.FullDefinition {
|
||||
|
||||
@@ -55,7 +55,6 @@ func NewResolver(index *SpecIndex) *Resolver {
|
||||
return nil
|
||||
}
|
||||
r := &Resolver{
|
||||
|
||||
specIndex: index,
|
||||
resolvedRoot: index.GetRootNode(),
|
||||
}
|
||||
@@ -336,7 +335,7 @@ func (resolver *Resolver) isInfiniteCircularDependency(ref *Reference, visitedDe
|
||||
}
|
||||
|
||||
for refDefinition := range ref.RequiredRefProperties {
|
||||
r := resolver.specIndex.GetMappedReferences()[refDefinition]
|
||||
r := resolver.specIndex.SearchIndexForReference(refDefinition)
|
||||
if initialRef != nil && initialRef.Definition == r.Definition {
|
||||
return true, visitedDefinitions
|
||||
}
|
||||
@@ -434,11 +433,24 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
||||
|
||||
} else {
|
||||
|
||||
// split the full def into parts
|
||||
if filepath.IsAbs(exp[0]) {
|
||||
fullDef = value
|
||||
|
||||
} else {
|
||||
|
||||
// split the referring ref full def into parts
|
||||
fileDef := strings.Split(ref.FullDefinition, "#/")
|
||||
|
||||
// extract the location of the ref and build a full def path.
|
||||
fullDef = fmt.Sprintf("%s#/%s", fileDef[0], exp[1])
|
||||
fullDef, _ = filepath.Abs(filepath.Join(filepath.Dir(fileDef[0]), exp[0]))
|
||||
}
|
||||
|
||||
//// split the full def into parts
|
||||
//fileDef := strings.Split(ref.FullDefinition, "#/")
|
||||
//
|
||||
//// extract the location of the ref and build a full def path.
|
||||
//
|
||||
//fullDef = fmt.Sprintf("%s#/%s", fileDef[0], exp[1])
|
||||
|
||||
}
|
||||
} else {
|
||||
@@ -470,9 +482,9 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
||||
fileDef := strings.Split(ref.FullDefinition, "#/")
|
||||
|
||||
// extract the location of the ref and build a full def path.
|
||||
loc, _ := filepath.Abs(filepath.Join(filepath.Dir(fileDef[0]), exp[0]))
|
||||
//loc, _ := filepath.Abs(fileDef[0]), exp[1]))
|
||||
|
||||
fullDef = fmt.Sprintf("%s#/%s", loc, exp[1])
|
||||
fullDef = fmt.Sprintf("%s#/%s", fileDef[0], exp[1])
|
||||
|
||||
}
|
||||
|
||||
@@ -505,7 +517,6 @@ func (resolver *Resolver) extractRelatives(ref *Reference, node, parent *yaml.No
|
||||
|
||||
} else {
|
||||
|
||||
// extract the location of the ref and build a full def path.
|
||||
fullDef, _ = filepath.Abs(filepath.Join(filepath.Dir(fileDef[0]), exp[0]))
|
||||
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ func (r *Rolodex) IndexTheRolodex() error {
|
||||
|
||||
// for each index, we need a resolver
|
||||
resolver := NewResolver(idx)
|
||||
idx.resolver = resolver
|
||||
// idx.resolver = resolver
|
||||
|
||||
// check if the config has been set to ignore circular references in arrays and polymorphic schemas
|
||||
if copiedConfig.IgnoreArrayCircularReferences {
|
||||
@@ -384,6 +384,7 @@ func (r *Rolodex) IndexTheRolodex() error {
|
||||
|
||||
index := NewSpecIndexWithConfig(r.rootNode, r.indexConfig)
|
||||
resolver := NewResolver(index)
|
||||
|
||||
if r.indexConfig.IgnoreArrayCircularReferences {
|
||||
resolver.IgnoreArrayCircularReferences()
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ type RemoteFS struct {
|
||||
remoteErrors []error
|
||||
logger *slog.Logger
|
||||
defaultClient *http.Client
|
||||
extractedFiles map[string]RolodexFile
|
||||
}
|
||||
|
||||
type RemoteFile struct {
|
||||
@@ -158,7 +159,8 @@ func (f *RemoteFile) Index(config *SpecIndexConfig) (*SpecIndex, error) {
|
||||
}
|
||||
|
||||
index := NewSpecIndexWithConfig(info.RootNode, config)
|
||||
index.specAbsolutePath = f.fullPath
|
||||
|
||||
index.specAbsolutePath = config.SpecAbsolutePath
|
||||
f.index = index
|
||||
return index, nil
|
||||
}
|
||||
@@ -233,6 +235,7 @@ func (i *RemoteFS) GetFiles() map[string]RolodexFile {
|
||||
files[key.(string)] = value.(*RemoteFile)
|
||||
return true
|
||||
})
|
||||
i.extractedFiles = files
|
||||
return files
|
||||
}
|
||||
|
||||
@@ -302,6 +305,7 @@ func (i *RemoteFS) Open(remoteURL string) (fs.File, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
remoteParsedURLOriginal, _ := url.Parse(remoteURL)
|
||||
|
||||
// try path first
|
||||
if r, ok := i.Files.Load(remoteParsedURL.Path); ok {
|
||||
@@ -418,7 +422,7 @@ func (i *RemoteFS) Open(remoteURL string) (fs.File, error) {
|
||||
|
||||
copiedCfg := *i.indexConfig
|
||||
|
||||
newBase := fmt.Sprintf("%s://%s%s", remoteParsedURL.Scheme, remoteParsedURL.Host,
|
||||
newBase := fmt.Sprintf("%s://%s%s", remoteParsedURLOriginal.Scheme, remoteParsedURLOriginal.Host,
|
||||
filepath.Dir(remoteParsedURL.Path))
|
||||
newBaseURL, _ := url.Parse(newBase)
|
||||
|
||||
|
||||
@@ -33,8 +33,19 @@ func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) *
|
||||
roloLookup, _ = filepath.Abs(filepath.Join(absPath, uri[0]))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
//roloLookup = absPath // hang on a jiffy whiffy
|
||||
if filepath.Ext(uri[1]) != "" {
|
||||
roloLookup = absPath
|
||||
} else {
|
||||
roloLookup = ""
|
||||
}
|
||||
ref = fmt.Sprintf("#/%s", uri[1])
|
||||
|
||||
ref = fmt.Sprintf("%s#/%s", absPath, uri[1])
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
if filepath.IsAbs(uri[0]) {
|
||||
roloLookup = uri[0]
|
||||
@@ -65,7 +76,9 @@ func (index *SpecIndex) SearchIndexForReferenceByReference(fullRef *Reference) *
|
||||
|
||||
// extract the index from the rolodex file.
|
||||
idx := rFile.GetIndex()
|
||||
if index.resolver != nil {
|
||||
index.resolver.indexesVisited++
|
||||
}
|
||||
if idx != nil {
|
||||
|
||||
// check mapped refs.
|
||||
|
||||
@@ -212,6 +212,12 @@ func TestSpecIndex_DigitalOcean_FullCheckoutLocalResolve(t *testing.T) {
|
||||
assert.Len(t, index.GetMappedReferencesSequenced(), 299)
|
||||
assert.Len(t, index.GetMappedReferences(), 299)
|
||||
assert.Len(t, fileFS.GetErrors(), 0)
|
||||
|
||||
// check circular references
|
||||
rolo.CheckForCircularReferences()
|
||||
assert.Len(t, rolo.GetCaughtErrors(), 0)
|
||||
assert.Len(t, rolo.GetIgnoredCircularReferences(), 0)
|
||||
|
||||
}
|
||||
|
||||
func TestSpecIndex_DigitalOcean_LookupsNotAllowed(t *testing.T) {
|
||||
|
||||
@@ -6,6 +6,7 @@ package index
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
@@ -31,14 +32,14 @@ func (index *SpecIndex) extractDefinitionsAndSchemas(schemasNode *yaml.Node, pat
|
||||
Node: schema,
|
||||
Path: fmt.Sprintf("$.components.schemas.%s", name),
|
||||
ParentNode: schemasNode,
|
||||
RequiredRefProperties: extractDefinitionRequiredRefProperties(schemasNode, map[string][]string{}),
|
||||
RequiredRefProperties: extractDefinitionRequiredRefProperties(schemasNode, map[string][]string{}, fullDef),
|
||||
}
|
||||
index.allComponentSchemaDefinitions[def] = ref
|
||||
}
|
||||
}
|
||||
|
||||
// extractDefinitionRequiredRefProperties goes through the direct properties of a schema and extracts the map of required definitions from within it
|
||||
func extractDefinitionRequiredRefProperties(schemaNode *yaml.Node, reqRefProps map[string][]string) map[string][]string {
|
||||
func extractDefinitionRequiredRefProperties(schemaNode *yaml.Node, reqRefProps map[string][]string, fulldef string) map[string][]string {
|
||||
if schemaNode == nil {
|
||||
return reqRefProps
|
||||
}
|
||||
@@ -73,7 +74,7 @@ func extractDefinitionRequiredRefProperties(schemaNode *yaml.Node, reqRefProps m
|
||||
// Check to see if the current property is directly embedded within the current schema, and handle its properties if so
|
||||
_, paramPropertiesMapNode := utils.FindKeyNodeTop("properties", param.Content)
|
||||
if paramPropertiesMapNode != nil {
|
||||
reqRefProps = extractDefinitionRequiredRefProperties(param, reqRefProps)
|
||||
reqRefProps = extractDefinitionRequiredRefProperties(param, reqRefProps, fulldef)
|
||||
}
|
||||
|
||||
// Check to see if the current property is polymorphic, and dive into that model if so
|
||||
@@ -81,7 +82,7 @@ func extractDefinitionRequiredRefProperties(schemaNode *yaml.Node, reqRefProps m
|
||||
_, ofNode := utils.FindKeyNodeTop(key, param.Content)
|
||||
if ofNode != nil {
|
||||
for _, ofNodeItem := range ofNode.Content {
|
||||
reqRefProps = extractRequiredReferenceProperties(ofNodeItem, name, reqRefProps)
|
||||
reqRefProps = extractRequiredReferenceProperties(fulldef, ofNodeItem, name, reqRefProps)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -94,14 +95,14 @@ func extractDefinitionRequiredRefProperties(schemaNode *yaml.Node, reqRefProps m
|
||||
continue
|
||||
}
|
||||
|
||||
reqRefProps = extractRequiredReferenceProperties(requiredPropDefNode, requiredPropertyNode.Value, reqRefProps)
|
||||
reqRefProps = extractRequiredReferenceProperties(fulldef, requiredPropDefNode, requiredPropertyNode.Value, reqRefProps)
|
||||
}
|
||||
|
||||
return reqRefProps
|
||||
}
|
||||
|
||||
// extractRequiredReferenceProperties returns a map of definition names to the property or properties which reference it within a node
|
||||
func extractRequiredReferenceProperties(requiredPropDefNode *yaml.Node, propName string, reqRefProps map[string][]string) map[string][]string {
|
||||
func extractRequiredReferenceProperties(fulldef string, requiredPropDefNode *yaml.Node, propName string, reqRefProps map[string][]string) map[string][]string {
|
||||
isRef, _, defPath := utils.IsNodeRefValue(requiredPropDefNode)
|
||||
if !isRef {
|
||||
_, defItems := utils.FindKeyNodeTop("items", requiredPropDefNode.Content)
|
||||
@@ -114,6 +115,69 @@ func extractRequiredReferenceProperties(requiredPropDefNode *yaml.Node, propName
|
||||
return reqRefProps
|
||||
}
|
||||
|
||||
// explode defpath
|
||||
exp := strings.Split(defPath, "#/")
|
||||
if len(exp) == 2 {
|
||||
if exp[0] != "" {
|
||||
if !strings.HasPrefix(exp[0], "http") {
|
||||
|
||||
if !filepath.IsAbs(exp[0]) {
|
||||
|
||||
if strings.HasPrefix(fulldef, "http") {
|
||||
|
||||
u, _ := url.Parse(fulldef)
|
||||
p := filepath.Dir(u.Path)
|
||||
abs, _ := filepath.Abs(filepath.Join(p, exp[0]))
|
||||
u.Path = abs
|
||||
defPath = fmt.Sprintf("%s#/%s", u.String(), exp[1])
|
||||
|
||||
} else {
|
||||
|
||||
abs, _ := filepath.Abs(filepath.Join(filepath.Dir(fulldef), exp[0]))
|
||||
defPath = fmt.Sprintf("%s#/%s", abs, exp[1])
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if strings.HasPrefix(exp[0], "http") {
|
||||
|
||||
defPath = exp[0]
|
||||
|
||||
} else {
|
||||
|
||||
// file shit again
|
||||
|
||||
if filepath.IsAbs(exp[0]) {
|
||||
|
||||
defPath = exp[0]
|
||||
|
||||
} else {
|
||||
|
||||
// check full def and decide what to do next.
|
||||
if strings.HasPrefix(fulldef, "http") {
|
||||
|
||||
u, _ := url.Parse(fulldef)
|
||||
p := filepath.Dir(u.Path)
|
||||
abs, _ := filepath.Abs(filepath.Join(p, exp[0]))
|
||||
u.Path = abs
|
||||
defPath = u.String()
|
||||
|
||||
} else {
|
||||
|
||||
defPath, _ = filepath.Abs(filepath.Join(filepath.Dir(fulldef), exp[0]))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if _, ok := reqRefProps[defPath]; !ok {
|
||||
reqRefProps[defPath] = []string{}
|
||||
}
|
||||
|
||||
@@ -49,5 +49,5 @@ func TestGenerateCleanSpecConfigBaseURL_HttpStrip(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSpecIndex_extractDefinitionRequiredRefProperties(t *testing.T) {
|
||||
assert.Nil(t, extractDefinitionRequiredRefProperties(nil, nil))
|
||||
assert.Nil(t, extractDefinitionRequiredRefProperties(nil, nil, ""))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user