Low-level docs for v3 model are now in place

5/6 of the way there!
This commit is contained in:
Dave Shanley
2022-09-21 07:10:58 -04:00
parent d4857ffe05
commit f9016b8414
25 changed files with 351 additions and 88 deletions

View File

@@ -8,7 +8,7 @@ import (
low "github.com/pb33f/libopenapi/datamodel/low/v3"
)
// Link represents an OpenAPI 3+ Link object that is backed by a low-level one.
// Link represents a high-level OpenAPI 3+ Link object that is backed by a low-level one.
//
// The Link object represents a possible design-time link for a response. The presence of a link does not guarantee the
// callers ability to successfully invoke it, rather it provides a known relationship and traversal mechanism between

View File

@@ -9,6 +9,7 @@ import (
)
// Operation is a high-level representation of an OpenAPI 3+ Operation object, backed by a low-level one.
//
// An Operation is perhaps the most important object of the entire specification. Everything of value
// happens here. The entire being for existence of this library and the specification, is this Operation.
// - https://spec.openapis.org/oas/v3.1.0#operation-object

View File

@@ -8,7 +8,8 @@ import (
low "github.com/pb33f/libopenapi/datamodel/low/v3"
)
// RequestBody represents a high-level OpenAPI 3+ RequestBody object,
// RequestBody represents a high-level OpenAPI 3+ RequestBody object, backed by a low-level one.
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
type RequestBody struct {
Description string
Content map[string]*MediaType
@@ -17,6 +18,7 @@ type RequestBody struct {
low *low.RequestBody
}
// NewRequestBody will create a new high-level RequestBody instance, from a low-level one.
func NewRequestBody(rb *low.RequestBody) *RequestBody {
r := new(RequestBody)
r.low = rb
@@ -27,6 +29,7 @@ func NewRequestBody(rb *low.RequestBody) *RequestBody {
return r
}
// GoLow returns the low-level RequestBody instance used to create the high-level one.
func (r *RequestBody) GoLow() *low.RequestBody {
return r.low
}

View File

@@ -12,7 +12,8 @@ import low "github.com/pb33f/libopenapi/datamodel/low/v3"
// to a security scheme declared in the Security Schemes under the Components Object.
//
// Security Requirement Objects that contain multiple schemes require that all schemes MUST be satisfied for a
// request to be authorized. This enables support for scenarios where multiple query parameters or HTTP headers are required to convey security information.
// request to be authorized. This enables support for scenarios where multiple query parameters or HTTP headers are
// required to convey security information.
//
// When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object, only one of the
// Security Requirement Objects in the list needs to be satisfied to authorize the request.

View File

@@ -9,15 +9,24 @@ import (
"gopkg.in/yaml.v3"
)
// Callback represents a low-level Callback object for OpenAPI 3+.
//
// A map of possible out-of band callbacks related to the parent operation. Each value in the map is a
// PathItem Object that describes a set of requests that may be initiated by the API provider and the expected
// responses. The key value used to identify the path item object is an expression, evaluated at runtime,
// that identifies a URL to use for the callback operation.
// - https://spec.openapis.org/oas/v3.1.0#callback-object
type Callback struct {
Expression low.ValueReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]]
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExpression will locate a string expression and return a ValueReference containing the located PathItem
func (cb *Callback) FindExpression(exp string) *low.ValueReference[*PathItem] {
return low.FindItemInMap[*PathItem](exp, cb.Expression.Value)
}
// Build will extract extensions, expressions and PathItem objects for Callback
func (cb *Callback) Build(root *yaml.Node, idx *index.SpecIndex) error {
cb.Extensions = low.ExtractExtensions(root)

View File

@@ -13,11 +13,11 @@ import (
"strings"
)
const (
ComponentsLabel = "components"
SchemasLabel = "schemas"
)
// Components represents a low-level OpenAPI 3+ Components Object, that is backed by a low-level one.
//
// Holds a set of reusable objects for different aspects of the OAS. All objects defined within the components object
// will have no effect on the API unless they are explicitly referenced from properties outside the components object.
// - https://spec.openapis.org/oas/v3.1.0#components-object
type Components struct {
Schemas low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*base.SchemaProxy]]
Responses low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Response]]
@@ -31,26 +31,32 @@ type Components struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExtension attempts to locate an extension with the supplied key
func (co *Components) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, co.Extensions)
}
// FindSchema attempts to locate a SchemaProxy from 'schemas' with a specific name
func (co *Components) FindSchema(schema string) *low.ValueReference[*base.SchemaProxy] {
return low.FindItemInMap[*base.SchemaProxy](schema, co.Schemas.Value)
}
// FindResponse attempts to locate a Response from 'responses' with a specific name
func (co *Components) FindResponse(response string) *low.ValueReference[*Response] {
return low.FindItemInMap[*Response](response, co.Responses.Value)
}
// FindParameter attempts to locate a Parameter from 'parameters' with a specific name
func (co *Components) FindParameter(response string) *low.ValueReference[*Parameter] {
return low.FindItemInMap[*Parameter](response, co.Parameters.Value)
}
// FindSecurityScheme attempts to locate a SecurityScheme from 'securitySchemes' with a specific name
func (co *Components) FindSecurityScheme(sScheme string) *low.ValueReference[*SecurityScheme] {
return low.FindItemInMap[*SecurityScheme](sScheme, co.SecuritySchemes.Value)
}
// FindExample attempts tp
func (co *Components) FindExample(example string) *low.ValueReference[*base.Example] {
return low.FindItemInMap[*base.Example](example, co.Examples.Value)
}

View File

@@ -0,0 +1,41 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT
package v3
// Label definitions used to look up vales in yaml.Node tree.
const (
ComponentsLabel = "components"
SchemasLabel = "schemas"
EncodingLabel = "encoding"
HeadersLabel = "headers"
ParametersLabel = "parameters"
RequestBodyLabel = "requestBody"
RequestBodiesLabel = "requestBodies"
ResponsesLabel = "responses"
CallbacksLabel = "callbacks"
ContentLabel = "content"
PathsLabel = "paths"
WebhooksLabel = "webhooks"
JSONSchemaDialectLabel = "jsonSchemaDialect"
GetLabel = "get"
PostLabel = "post"
PatchLabel = "patch"
PutLabel = "put"
DeleteLabel = "delete"
OptionsLabel = "options"
HeadLabel = "head"
TraceLabel = "trace"
LinksLabel = "links"
DefaultLabel = "default"
SecurityLabel = "security"
SecuritySchemesLabel = "securitySchemes"
OAuthFlowsLabel = "flows"
VariablesLabel = "variables"
ServersLabel = "servers"
ServerLabel = "server"
ImplicitLabel = "implicit"
PasswordLabel = "password"
ClientCredentialsLabel = "clientCredentials"
AuthorizationCodeLabel = "authorizationCode"
)

View File

@@ -1,6 +1,7 @@
package v3
import (
"fmt"
"github.com/pb33f/libopenapi/datamodel"
"github.com/pb33f/libopenapi/datamodel/low/base"
"github.com/stretchr/testify/assert"
@@ -577,3 +578,28 @@ func TestCreateDocument_ExternalDoc_Error(t *testing.T) {
_, err = CreateDocument(info)
assert.Len(t, err, 1)
}
func ExampleCreateDocument() {
// How to create a low-level OpenAPI 3 Document
// load petstore into bytes
petstoreBytes, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
// read in specification
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
// build low-level document model
document, errors := CreateDocument(info)
// if something went wrong, a slice of errors is returned
if len(errors) > 0 {
for i := range errors {
fmt.Printf("error: %s\n", errors[i].Error())
}
panic("cannot build document")
}
// print out email address from the info > contact object.
fmt.Print(document.Info.Value.Contact.Value.Email.Value)
// Output: apiteam@swagger.io
}

View File

@@ -1,6 +1,11 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT
// Package v3 represents all OpenAPI 3+ low-level models. High-level models are more difficult to navigate
// than higher-level models, however they are packed with all the raw AST and node data required to perform
// any kind of analysis on the underlying data.
//
// Every property is wrapped in a NodeReference or a KeyReference or a ValueReference.
package v3
import (
@@ -10,21 +15,76 @@ import (
)
type Document struct {
Version low.ValueReference[string]
Info low.NodeReference[*base.Info]
JsonSchemaDialect low.NodeReference[string] // 3.1
Webhooks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]] // 3.1
Servers low.NodeReference[[]low.ValueReference[*Server]]
Paths low.NodeReference[*Paths]
Components low.NodeReference[*Components]
Security low.NodeReference[*SecurityRequirement]
Tags low.NodeReference[[]low.ValueReference[*base.Tag]]
ExternalDocs low.NodeReference[*base.ExternalDoc]
Extensions map[low.KeyReference[string]]low.ValueReference[any]
Index *index.SpecIndex
// Version is the version of OpenAPI being used, extracted from the 'openapi: x.x.x' definition.
// This is not a standard property of the OpenAPI model, it's a convenience mechanism only.
Version low.ValueReference[string]
// Info represents a specification Info definitions
// Provides metadata about the API. The metadata MAY be used by tooling as required.
// - https://spec.openapis.org/oas/v3.1.0#info-object
Info low.NodeReference[*base.Info]
// JsonSchemaDialect is a 3.1+ property that sets the dialect to use for validating *base.Schema definitions
// The default value for the $schema keyword within Schema Objects contained within this OAS document.
// This MUST be in the form of a URI.
// - https://spec.openapis.org/oas/v3.1.0#schema-object
JsonSchemaDialect low.NodeReference[string] // 3.1
// Webhooks is a 3.1+ property that is similar to callbacks, except, this defines incoming webhooks.
// The incoming webhooks that MAY be received as part of this API and that the API consumer MAY choose to implement.
// Closely related to the callbacks feature, this section describes requests initiated other than by an API call,
// for example by an out-of-band registration. The key name is a unique string to refer to each webhook,
// while the (optionally referenced) Path Item Object describes a request that may be initiated by the API provider
// and the expected responses. An example is available.
Webhooks low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*PathItem]] // 3.1
// Servers is a slice of Server instances which provide connectivity information to a target server. If the servers
// property is not provided, or is an empty array, the default value would be a Server Object with a url value of /.
// - https://spec.openapis.org/oas/v3.1.0#server-object
Servers low.NodeReference[[]low.ValueReference[*Server]]
// Paths contains all the PathItem definitions for the specification.
// The available paths and operations for the API, The most important part of ths spec.
// - https://spec.openapis.org/oas/v3.1.0#paths-object
Paths low.NodeReference[*Paths]
// Components is an element to hold various schemas for the document.
// - https://spec.openapis.org/oas/v3.1.0#components-object
Components low.NodeReference[*Components]
// Security contains global security requirements/roles for the specification
// A declaration of which security mechanisms can be used across the API. The list of values includes alternative
// security requirement objects that can be used. Only one of the security requirement objects need to be satisfied
// to authorize a request. Individual operations can override this definition. To make security optional,
// an empty security requirement ({}) can be included in the array.
// - https://spec.openapis.org/oas/v3.1.0#security-requirement-object
Security low.NodeReference[*SecurityRequirement]
// Tags is a slice of base.Tag instances defined by the specification
// A list of tags used by the document with additional metadata. The order of the tags can be used to reflect on
// their order by the parsing tools. Not all tags that are used by the Operation Object must be declared.
// The tags that are not declared MAY be organized randomly or based on the tools logic.
// Each tag name in the list MUST be unique.
// - https://spec.openapis.org/oas/v3.1.0#tag-object
Tags low.NodeReference[[]low.ValueReference[*base.Tag]]
// ExternalDocs is an instance of base.ExternalDoc for.. well, obvious really, innit.
// - https://spec.openapis.org/oas/v3.1.0#external-documentation-object
ExternalDocs low.NodeReference[*base.ExternalDoc]
// Extensions contains all custom extensions defined for the top-level document.
Extensions map[low.KeyReference[string]]low.ValueReference[any]
// Index is a reference to the *index.SpecIndex that was created for the document and used
// as a guide when building out the Document. Ideal if further processing is required on the model and
// the original details are required to continue the work.
//
// This property is not a part of the OpenAPI schema, this is custom to libopenapi.
Index *index.SpecIndex
}
//
// TODO: this is early prototype mutation/modification code, keeping it around for later.
//func (d *Document) AddTag() *base.Tag {
// t := base.NewTag()
// //d.Tags.KeyNode

View File

@@ -9,10 +9,8 @@ import (
"gopkg.in/yaml.v3"
)
const (
EncodingLabel = "encoding"
)
// Encoding represents a low-level OpenAPI 3+ Encoding object
// - https://spec.openapis.org/oas/v3.1.0#encoding-object
type Encoding struct {
ContentType low.NodeReference[string]
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
@@ -21,12 +19,13 @@ type Encoding struct {
AllowReserved low.NodeReference[bool]
}
// FindHeader attempts to locate a Header with the supplied name
func (en *Encoding) FindHeader(hType string) *low.ValueReference[*Header] {
return low.FindItemInMap[*Header](hType, en.Headers.Value)
}
// Build will extract all Header objects from supplied node.
func (en *Encoding) Build(root *yaml.Node, idx *index.SpecIndex) error {
headers, hL, hN, err := low.ExtractMap[*Header](HeadersLabel, root, idx)
if err != nil {
return err
@@ -38,6 +37,5 @@ func (en *Encoding) Build(root *yaml.Node, idx *index.SpecIndex) error {
ValueNode: hN,
}
}
return nil
}

View File

@@ -0,0 +1,35 @@
// Copyright 2022 Princess B33f Heavy Industries / Dave Shanley
// SPDX-License-Identifier: MIT
package v3
import (
"fmt"
"github.com/pb33f/libopenapi/datamodel"
"io/ioutil"
)
func Example_createLowDocument() {
// How to create a low-level OpenAPI 3 Document
// load petstore into bytes
petstoreBytes, _ := ioutil.ReadFile("../../../test_specs/petstorev3.json")
// read in specification
info, _ := datamodel.ExtractSpecInfo(petstoreBytes)
// build low-level document model
document, errors := CreateDocument(info)
// if something went wrong, a slice of errors is returned
if len(errors) > 0 {
for i := range errors {
fmt.Printf("error: %s\n", errors[i].Error())
}
panic("cannot build document")
}
// print out email address from the info > contact object.
fmt.Print(document.Info.Value.Contact.Value.Email.Value)
// Output: apiteam@swagger.io
}

View File

@@ -11,10 +11,8 @@ import (
"gopkg.in/yaml.v3"
)
const (
HeadersLabel = "headers"
)
// Header represents a low-level OpenAPI 3+ Header object.
// - https://spec.openapis.org/oas/v3.1.0#header-object
type Header struct {
Description low.NodeReference[string]
Required low.NodeReference[bool]
@@ -30,18 +28,22 @@ type Header struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExtension will attempt to locate an extension with the supplied name
func (h *Header) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, h.Extensions)
}
// FindExample will attempt to locate an Example with a specified name
func (h *Header) FindExample(eType string) *low.ValueReference[*base.Example] {
return low.FindItemInMap[*base.Example](eType, h.Examples.Value)
}
// FindContent will attempt to locate a MediaType definition, with a specified name
func (h *Header) FindContent(ext string) *low.ValueReference[*MediaType] {
return low.FindItemInMap[*MediaType](ext, h.Content.Value)
}
// Build will extract extensions, examples, schema and content/media types from node.
func (h *Header) Build(root *yaml.Node, idx *index.SpecIndex) error {
h.Extensions = low.ExtractExtensions(root)
@@ -83,6 +85,5 @@ func (h *Header) Build(root *yaml.Node, idx *index.SpecIndex) error {
KeyNode: cL,
ValueNode: cN,
}
return nil
}

View File

@@ -9,6 +9,18 @@ import (
"gopkg.in/yaml.v3"
)
// Link represents a low-level OpenAPI 3+ Link object.
//
// The Link object represents a possible design-time link for a response. The presence of a link does not guarantee the
// callers ability to successfully invoke it, rather it provides a known relationship and traversal mechanism between
// responses and other operations.
//
// Unlike dynamic links (i.e. links provided in the response payload), the OAS linking mechanism does not require
// link information in the runtime response.
//
// For computing links, and providing instructions to execute them, a runtime expression is used for accessing values
// in an operation and using them as parameters while invoking the linked operation.
// - https://spec.openapis.org/oas/v3.1.0#link-object
type Link struct {
OperationRef low.NodeReference[string]
OperationId low.NodeReference[string]
@@ -19,14 +31,17 @@ type Link struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindParameter will attempt to locate a parameter string value, using a parameter name input.
func (l *Link) FindParameter(pName string) *low.ValueReference[string] {
return low.FindItemInMap[string](pName, l.Parameters.Value)
}
// FindExtension will attempt to locate an extension with a specific key
func (l *Link) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, l.Extensions)
}
// Build will extract extensions and servers from the node.
func (l *Link) Build(root *yaml.Node, idx *index.SpecIndex) error {
l.Extensions = low.ExtractExtensions(root)
@@ -36,6 +51,5 @@ func (l *Link) Build(root *yaml.Node, idx *index.SpecIndex) error {
return sErr
}
l.Server = ser
return nil
}

View File

@@ -11,6 +11,10 @@ import (
"gopkg.in/yaml.v3"
)
// MediaType represents a low-level OpenAPI MediaType object.
//
// Each Media Type Object provides schema and examples for the media type identified by its key.
// - https://spec.openapis.org/oas/v3.1.0#media-type-object
type MediaType struct {
Schema low.NodeReference[*base.SchemaProxy]
Example low.NodeReference[any]
@@ -19,22 +23,27 @@ type MediaType struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExtension will attempt to locate an extension with the supplied name.
func (mt *MediaType) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, mt.Extensions)
}
// FindPropertyEncoding will attempt to locate an Encoding value with a specific name.
func (mt *MediaType) FindPropertyEncoding(eType string) *low.ValueReference[*Encoding] {
return low.FindItemInMap[*Encoding](eType, mt.Encoding.Value)
}
// FindExample will attempt to locate an Example with a specific name.
func (mt *MediaType) FindExample(eType string) *low.ValueReference[*base.Example] {
return low.FindItemInMap[*base.Example](eType, mt.Examples.Value)
}
// GetAllExamples will extract all examples from the MediaType instance.
func (mt *MediaType) GetAllExamples() map[low.KeyReference[string]]low.ValueReference[*base.Example] {
return mt.Examples.Value
}
// Build will extract examples, extensions, schema and encoding from node.
func (mt *MediaType) Build(root *yaml.Node, idx *index.SpecIndex) error {
mt.Extensions = low.ExtractExtensions(root)

View File

@@ -9,13 +9,8 @@ import (
"gopkg.in/yaml.v3"
)
const (
ImplicitLabel = "implicit"
PasswordLabel = "password"
ClientCredentialsLabel = "clientCredentials"
AuthorizationCodeLabel = "authorizationCode"
)
// OAuthFlows represents a low-level OpenAPI 3+ OAuthFlows object.
// - https://spec.openapis.org/oas/v3.1.0#oauth-flows-object
type OAuthFlows struct {
Implicit low.NodeReference[*OAuthFlow]
Password low.NodeReference[*OAuthFlow]
@@ -24,10 +19,12 @@ type OAuthFlows struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExtension will attempt to locate an extension with the supplied name.
func (o *OAuthFlows) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, o.Extensions)
}
// Build will extract extensions and all OAuthFlow types from the supplied node.
func (o *OAuthFlows) Build(root *yaml.Node, idx *index.SpecIndex) error {
o.Extensions = low.ExtractExtensions(root)
@@ -58,6 +55,8 @@ func (o *OAuthFlows) Build(root *yaml.Node, idx *index.SpecIndex) error {
}
// OAuthFlow represents a low-level OpenAPI 3+ OAuthFlow object.
// - https://spec.openapis.org/oas/v3.1.0#oauth-flow-object
type OAuthFlow struct {
AuthorizationUrl low.NodeReference[string]
TokenUrl low.NodeReference[string]
@@ -66,14 +65,17 @@ type OAuthFlow struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindScope attempts to locate a scope using a specified name.
func (o *OAuthFlow) FindScope(scope string) *low.ValueReference[string] {
return low.FindItemInMap[string](scope, o.Scopes.Value)
}
// FindExtension attempts to locate an extension with a specified key
func (o *OAuthFlow) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, o.Extensions)
}
// Build will extract extensions from the node.
func (o *OAuthFlow) Build(root *yaml.Node, idx *index.SpecIndex) error {
o.Extensions = low.ExtractExtensions(root)
return nil

View File

@@ -10,14 +10,11 @@ import (
"gopkg.in/yaml.v3"
)
const (
ParametersLabel = "parameters"
RequestBodyLabel = "requestBody"
RequestBodiesLabel = "requestBodies"
ResponsesLabel = "responses"
CallbacksLabel = "callbacks"
)
// Operation is a low-level representation of an OpenAPI 3+ Operation object.
//
// An Operation is perhaps the most important object of the entire specification. Everything of value
// happens here. The entire being for existence of this library and the specification, is this Operation.
// - https://spec.openapis.org/oas/v3.1.0#operation-object
type Operation struct {
Tags low.NodeReference[[]low.ValueReference[string]]
Summary low.NodeReference[string]
@@ -34,10 +31,12 @@ type Operation struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindCallback will attempt to locate a Callback instance by the supplied name.
func (o *Operation) FindCallback(callback string) *low.ValueReference[*Callback] {
return low.FindItemInMap[*Callback](callback, o.Callbacks.Value)
}
// Build will extract external docs, parameters, request body, responses, callbacks, security and servers.
func (o *Operation) Build(root *yaml.Node, idx *index.SpecIndex) error {
o.Extensions = low.ExtractExtensions(root)

View File

@@ -11,10 +11,10 @@ import (
"gopkg.in/yaml.v3"
)
const (
ContentLabel = "content"
)
// Parameter represents a high-level OpenAPI 3+ Parameter object, that is backed by a low-level one.
//
// A unique parameter is defined by a combination of a name and location.
// - https://spec.openapis.org/oas/v3.1.0#parameter-object
type Parameter struct {
Name low.NodeReference[string]
In low.NodeReference[string]
@@ -32,18 +32,22 @@ type Parameter struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindContent will attempt to locate a MediaType instance using the specified name.
func (p *Parameter) FindContent(cType string) *low.ValueReference[*MediaType] {
return low.FindItemInMap[*MediaType](cType, p.Content.Value)
}
// FindExample will attempt to locate a base.Example instance using the specified name.
func (p *Parameter) FindExample(eType string) *low.ValueReference[*base.Example] {
return low.FindItemInMap[*base.Example](eType, p.Examples.Value)
}
// FindExtension attempts to locate an extension using the specified name.
func (p *Parameter) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, p.Extensions)
}
// Build will extract examples, extensions and content/media types.
func (p *Parameter) Build(root *yaml.Node, idx *index.SpecIndex) error {
p.Extensions = low.ExtractExtensions(root)

View File

@@ -13,6 +13,12 @@ import (
"sync"
)
// PathItem represents a low-level OpenAPI 3+ PathItem object.
//
// Describes the operations available on a single path. A Path Item MAY be empty, due to ACL constraints.
// The path itself is still exposed to the documentation viewer, but they will not know which operations and parameters
// are available.
// - https://spec.openapis.org/oas/v3.1.0#path-item-object
type PathItem struct {
Description low.NodeReference[string]
Summary low.NodeReference[string]
@@ -29,10 +35,13 @@ type PathItem struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExtension attempts to find an extension
func (p *PathItem) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, p.Extensions)
}
// Build extracts extensions, parameters, servers and each http method defined.
// everything is extracted asynchronously for speed.
func (p *PathItem) Build(root *yaml.Node, idx *index.SpecIndex) error {
p.Extensions = low.ExtractExtensions(root)
skip := false
@@ -204,6 +213,5 @@ func (p *PathItem) Build(root *yaml.Node, idx *index.SpecIndex) error {
if len(ops) > 0 {
wg.Wait()
}
return nil
}

View File

@@ -12,25 +12,18 @@ import (
"strings"
)
const (
PathsLabel = "paths"
WebhooksLabel = "webhooks"
JSONSchemaDialectLabel = "jsonSchemaDialect"
GetLabel = "get"
PostLabel = "post"
PatchLabel = "patch"
PutLabel = "put"
DeleteLabel = "delete"
OptionsLabel = "options"
HeadLabel = "head"
TraceLabel = "trace"
)
// Paths represents a high-level OpenAPI 3+ Paths object, that is backed by a low-level one.
//
// Holds the relative paths to the individual endpoints and their operations. The path is appended to the URL from the
// Server Object in order to construct the full URL. The Paths MAY be empty, due to Access Control List (ACL)
// constraints.
// - https://spec.openapis.org/oas/v3.1.0#paths-object
type Paths struct {
PathItems map[low.KeyReference[string]]low.ValueReference[*PathItem]
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindPath will attempt to locate a PathItem using the provided path string.
func (p *Paths) FindPath(path string) *low.ValueReference[*PathItem] {
for k, j := range p.PathItems {
if k.Value == path {
@@ -40,10 +33,12 @@ func (p *Paths) FindPath(path string) *low.ValueReference[*PathItem] {
return nil
}
// FindExtension will attempt to locate an extension using the specified string.
func (p *Paths) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, p.Extensions)
}
// Build will extract extensions and all PathItems. This happens asynchronously for speed.
func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
p.Extensions = low.ExtractExtensions(root)
skip := false
@@ -126,5 +121,4 @@ func (p *Paths) Build(root *yaml.Node, idx *index.SpecIndex) error {
}
p.PathItems = pathsMap
return nil
}

View File

@@ -9,6 +9,8 @@ import (
"gopkg.in/yaml.v3"
)
// RequestBody represents a low-level OpenAPI 3+ RequestBody object.
// - https://spec.openapis.org/oas/v3.1.0#request-body-object
type RequestBody struct {
Description low.NodeReference[string]
Content low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*MediaType]]
@@ -16,14 +18,17 @@ type RequestBody struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// FindExtension attemps to locate an extension using the provided name.
func (rb *RequestBody) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, rb.Extensions)
}
// FindContent attempts to find content/MediaType defined using a specified name.
func (rb *RequestBody) FindContent(cType string) *low.ValueReference[*MediaType] {
return low.FindItemInMap[*MediaType](cType, rb.Content.Value)
}
// Build will extract extensions and MediaType objects from the node.
func (rb *RequestBody) Build(root *yaml.Node, idx *index.SpecIndex) error {
rb.Extensions = low.ExtractExtensions(root)

View File

@@ -11,16 +11,26 @@ import (
"gopkg.in/yaml.v3"
)
const (
LinksLabel = "links"
DefaultLabel = "default"
)
// Responses represents a low-level OpenAPI 3+ Responses object.
//
// It's a container for the expected responses of an operation. The container maps a HTTP response code to the
// expected response.
//
// The specification is not necessarily expected to cover all possible HTTP response codes because they may not be
// known in advance. However, documentation is expected to cover a successful operation response and any known errors.
//
// The default MAY be used as a default response object for all HTTP codes that are not covered individually by
// the Responses Object.
//
// The Responses Object MUST contain at least one response code, and if only one response code is provided it SHOULD
// be the response for a successful operation call.
// - https://spec.openapis.org/oas/v3.1.0#responses-object
type Responses struct {
Codes map[low.KeyReference[string]]low.ValueReference[*Response]
Default low.NodeReference[*Response]
}
// Build will extract default response and all Response objects for each code
func (r *Responses) Build(root *yaml.Node, idx *index.SpecIndex) error {
if utils.IsNodeMap(root) {
codes, err := low.ExtractMapNoLookup[*Response](root, idx)
@@ -39,15 +49,22 @@ func (r *Responses) Build(root *yaml.Node, idx *index.SpecIndex) error {
r.Default = def
}
} else {
return fmt.Errorf("responses build failed: vn node is not a map! line %d, col %d", root.Line, root.Column)
return fmt.Errorf("responses build failed: vn node is not a map! line %d, col %d",
root.Line, root.Column)
}
return nil
}
// FindResponseByCode will attempt to locate a Response using an HTTP response code.
func (r *Responses) FindResponseByCode(code string) *low.ValueReference[*Response] {
return low.FindItemInMap[*Response](code, r.Codes)
}
// Response represents a high-level OpenAPI 3+ Response object that is backed by a low-level one.
//
// Describes a single response from an API Operation, including design-time, static links to
// operations based on the response.
// - https://spec.openapis.org/oas/v3.1.0#response-object
type Response struct {
Description low.NodeReference[string]
Headers low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Header]]
@@ -56,22 +73,27 @@ type Response struct {
Links low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*Link]]
}
// FindExtension will attempt to locate an extension using the supplied key
func (r *Response) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, r.Extensions)
}
// FindContent will attempt to locate a MediaType instance using the supplied key.
func (r *Response) FindContent(cType string) *low.ValueReference[*MediaType] {
return low.FindItemInMap[*MediaType](cType, r.Content.Value)
}
// FindHeader will attempt to locate a Header instance using the supplied key.
func (r *Response) FindHeader(hType string) *low.ValueReference[*Header] {
return low.FindItemInMap[*Header](hType, r.Headers.Value)
}
// FindLink will attempt to locate a Link instance using the supplied key.
func (r *Response) FindLink(hType string) *low.ValueReference[*Link] {
return low.FindItemInMap[*Link](hType, r.Links.Value)
}
// Build will extract headers, extensions, content and links from node.
func (r *Response) Build(root *yaml.Node, idx *index.SpecIndex) error {
r.Extensions = low.ExtractExtensions(root)

View File

@@ -10,12 +10,16 @@ import (
"gopkg.in/yaml.v3"
)
const (
SecurityLabel = "security"
SecuritySchemesLabel = "securitySchemes"
OAuthFlowsLabel = "flows"
)
// SecurityScheme represents a low-level OpenAPI 3+ SecurityScheme object.
//
// Defines a security scheme that can be used by the operations.
//
// Supported schemes are HTTP authentication, an API key (either as a header, a cookie parameter or as a query parameter),
// mutual TLS (use of a client certificate), OAuth2s common flows (implicit, password, client credentials and
// authorization code) as defined in RFC6749 (https://www.rfc-editor.org/rfc/rfc6749), and OpenID Connect Discovery.
// Please note that as of 2020, the implicit flow is about to be deprecated by OAuth 2.0 Security Best Current Practice.
// Recommended for most use case is Authorization Code Grant flow with PKCE.
// - https://spec.openapis.org/oas/v3.1.0#security-scheme-object
type SecurityScheme struct {
Type low.NodeReference[string]
Description low.NodeReference[string]
@@ -28,14 +32,28 @@ type SecurityScheme struct {
Extensions map[low.KeyReference[string]]low.ValueReference[any]
}
// SecurityRequirement is a low-level representation of an OpenAPI 3+ SecurityRequirement object.
//
// It lists the required security schemes to execute this operation. The name used for each property MUST correspond
// to a security scheme declared in the Security Schemes under the Components Object.
//
// Security Requirement Objects that contain multiple schemes require that all schemes MUST be satisfied for a
// request to be authorized. This enables support for scenarios where multiple query parameters or HTTP headers are
// required to convey security information.
//
// When a list of Security Requirement Objects is defined on the OpenAPI Object or Operation Object, only one of the
// Security Requirement Objects in the list needs to be satisfied to authorize the request.
// - https://spec.openapis.org/oas/v3.1.0#security-requirement-object
type SecurityRequirement struct {
ValueRequirements []low.ValueReference[map[low.KeyReference[string]][]low.ValueReference[string]]
}
// FindExtension attempts to locate an extension using the supplied key.
func (ss *SecurityScheme) FindExtension(ext string) *low.ValueReference[any] {
return low.FindItemInMap[any](ext, ss.Extensions)
}
// Build will extract OAuthFlows and extensions from the node.
func (ss *SecurityScheme) Build(root *yaml.Node, idx *index.SpecIndex) error {
ss.Extensions = low.ExtractExtensions(root)
@@ -50,6 +68,7 @@ func (ss *SecurityScheme) Build(root *yaml.Node, idx *index.SpecIndex) error {
return nil
}
// FindRequirement will attempt to locate a security requirement string from a supplied name.
func (sr *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string] {
for _, r := range sr.ValueRequirements {
for k, v := range r.Value {
@@ -61,6 +80,7 @@ func (sr *SecurityRequirement) FindRequirement(name string) []low.ValueReference
return nil
}
// Build will extract all security requirements
func (sr *SecurityRequirement) Build(root *yaml.Node, idx *index.SpecIndex) error {
if utils.IsNodeArray(root) {
var requirements []low.ValueReference[map[low.KeyReference[string]][]low.ValueReference[string]]

View File

@@ -10,22 +10,20 @@ import (
"gopkg.in/yaml.v3"
)
const (
VariablesLabel = "variables"
ServersLabel = "servers"
ServerLabel = "server"
)
// Server represents a low-level OpenAPI 3+ Server object.
// - https://spec.openapis.org/oas/v3.1.0#server-object
type Server struct {
URL low.NodeReference[string]
Description low.NodeReference[string]
Variables low.NodeReference[map[low.KeyReference[string]]low.ValueReference[*ServerVariable]]
}
func (s *Server) FindVariable(ext string) *low.ValueReference[*ServerVariable] {
return low.FindItemInMap[*ServerVariable](ext, s.Variables.Value)
// FindVariable attempts to locate a ServerVariable instance using the supplied key.
func (s *Server) FindVariable(serverVar string) *low.ValueReference[*ServerVariable] {
return low.FindItemInMap[*ServerVariable](serverVar, s.Variables.Value)
}
// Build will extract server variables from the supplied node.
func (s *Server) Build(root *yaml.Node, idx *index.SpecIndex) error {
kn, vars := utils.FindKeyNode(VariablesLabel, root.Content)
if vars == nil {

View File

@@ -4,6 +4,13 @@ import (
"github.com/pb33f/libopenapi/datamodel/low"
)
// ServerVariable represents a low-level OpenAPI 3+ ServerVariable object.
//
// ServerVariable is an object representing a Server Variable for server URL template substitution.
// - https://spec.openapis.org/oas/v3.1.0#server-variable-object
//
// This is the only struct that is not Buildable, it's not used by anything other than a Server instance,
// and it has nothing to build that requires it to be buildable.
type ServerVariable struct {
Enum []low.NodeReference[string]
Default low.NodeReference[string]