Files
libopenapi/bundler/bundler.go
quobix 2bc6e9f028 Added ‘bundler’ module
resolves a v3 document or a model into a single document.

Signed-off-by: quobix <dave@quobix.com>
2024-01-18 15:11:39 -05:00

71 lines
2.5 KiB
Go

// Copyright 2023-2024 Princess Beef Heavy Industries, LLC / Dave Shanley
// https://pb33f.io
// SPDX-License-Identifier: MIT
package bundler
import (
"errors"
"github.com/pb33f/libopenapi"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/high/v3"
"github.com/pb33f/libopenapi/index"
)
// BundleBytes will take a byte slice of an OpenAPI specification and return a bundled version of it.
// This is useful for when you want to take a specification with external references, and you want to bundle it
// into a single document.
//
// This function will 'resolve' all references in the specification and return a single document. The resulting
// document will be a valid OpenAPI specification, containing no references.
//
// Circular references will not be resolved and will be skipped.
func BundleBytes(bytes []byte, configuration *datamodel.DocumentConfiguration) ([]byte, error) {
doc, err := libopenapi.NewDocumentWithConfiguration(bytes, configuration)
if err != nil {
return nil, err
}
v3Doc, errs := doc.BuildV3Model()
err = errors.Join(errs...)
bundledBytes, e := BundleDocument(&v3Doc.Model)
return bundledBytes, errors.Join(err, e)
}
// BundleDocument will take a v3.Document and return a bundled version of it.
// This is useful for when you want to take a document that has been built
// from a specification with external references, and you want to bundle it
// into a single document.
//
// This function will 'resolve' all references in the specification and return a single document. The resulting
// document will be a valid OpenAPI specification, containing no references.
//
// Circular references will not be resolved and will be skipped.
func BundleDocument(model *v3.Document) ([]byte, error) {
rolodex := model.Rolodex
compress := func(idx *index.SpecIndex) {
mappedReferences := idx.GetMappedReferences()
sequencedReferences := idx.GetRawReferencesSequenced()
for _, sequenced := range sequencedReferences {
mappedReference := mappedReferences[sequenced.FullDefinition]
if mappedReference != nil && !mappedReference.Circular {
sequenced.Node.Content = mappedReference.Node.Content
}
if mappedReference != nil && mappedReference.Circular {
if idx.GetLogger() != nil {
idx.GetLogger().Warn("[bundler] skipping circular reference",
"ref", sequenced.FullDefinition)
}
}
}
}
indexes := rolodex.GetIndexes()
compress(rolodex.GetRootIndex())
for _, idx := range indexes {
compress(idx)
}
return model.Render()
}