base

package
v0.16.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 10, 2024 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package base contains shared low-level models that are used between both versions 2 and 3 of OpenAPI. These models are consistent across both specifications, except for the Schema.

OpenAPI 3 contains all the same properties that an OpenAPI 2 specification does, and more. The choice to not duplicate the schemas is to allow a graceful degradation pattern to be used. Schemas are the most complex beats, particularly when polymorphism is used. By re-using the same superset Schema across versions, we can ensure that all the latest features are collected, without damaging backwards compatibility.

Index

Constants

View Source
const (
	VersionLabel               = "version"
	TermsOfServiceLabel        = "termsOfService"
	DescriptionLabel           = "description"
	TitleLabel                 = "title"
	EmailLabel                 = "email"
	NameLabel                  = "name"
	URLLabel                   = "url"
	TagsLabel                  = "tags"
	ExternalDocsLabel          = "externalDocs"
	ExamplesLabel              = "examples"
	ExampleLabel               = "example"
	ValueLabel                 = "value"
	InfoLabel                  = "info"
	ContactLabel               = "contact"
	LicenseLabel               = "license"
	PropertiesLabel            = "properties"
	DependentSchemasLabel      = "dependentSchemas"
	PatternPropertiesLabel     = "patternProperties"
	IfLabel                    = "if"
	ElseLabel                  = "else"
	ThenLabel                  = "then"
	PropertyNamesLabel         = "propertyNames"
	UnevaluatedItemsLabel      = "unevaluatedItems"
	UnevaluatedPropertiesLabel = "unevaluatedProperties"
	AdditionalPropertiesLabel  = "additionalProperties"
	XMLLabel                   = "xml"
	ItemsLabel                 = "items"
	PrefixItemsLabel           = "prefixItems"
	ContainsLabel              = "contains"
	AllOfLabel                 = "allOf"
	AnyOfLabel                 = "anyOf"
	OneOfLabel                 = "oneOf"
	NotLabel                   = "not"
	TypeLabel                  = "type"
	DiscriminatorLabel         = "discriminator"
	ExclusiveMinimumLabel      = "exclusiveMinimum"
	ExclusiveMaximumLabel      = "exclusiveMaximum"
	SchemaLabel                = "schema"
	SchemaTypeLabel            = "$schema"
	AnchorLabel                = "$anchor"
)

Constants for labels used to look up values within OpenAPI specifications.

Variables

This section is empty.

Functions

func ExtractSchema

func ExtractSchema(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) (*low.NodeReference[*SchemaProxy], error)

ExtractSchema will return a pointer to a NodeReference that contains a *SchemaProxy if successful. The function will specifically look for a key node named 'schema' and extract the value mapped to that key. If the operation fails then no NodeReference is returned and an error is returned instead.

Types

type Contact

type Contact struct {
	Name     low.NodeReference[string]
	URL      low.NodeReference[string]
	Email    low.NodeReference[string]
	KeyNode  *yaml.Node
	RootNode *yaml.Node
	*low.Reference
}

Contact represents a low-level representation of the Contact definitions found at

v2 - https://swagger.io/specification/v2/#contactObject
v3 - https://spec.openapis.org/oas/v3.1.0#contact-object

func (*Contact) Build

func (c *Contact) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error

Build is not implemented for Contact (there is nothing to build).

func (*Contact) Hash

func (c *Contact) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the Contact object

type Discriminator

type Discriminator struct {
	PropertyName low.NodeReference[string]
	Mapping      low.NodeReference[*orderedmap.Map[low.KeyReference[string], low.ValueReference[string]]]
	low.Reference
}

Discriminator is only used by OpenAPI 3+ documents, it represents a polymorphic discriminator used for schemas

When request bodies or response payloads may be one of a number of different schemas, a discriminator object can be used to aid in serialization, deserialization, and validation. The discriminator is a specific object in a schema which is used to inform the consumer of the document of an alternative schema based on the value associated with it.

When using the discriminator, inline schemas will not be considered.

v3 - https://spec.openapis.org/oas/v3.1.0#discriminator-object

func (*Discriminator) FindMappingValue

func (d *Discriminator) FindMappingValue(key string) *low.ValueReference[string]

FindMappingValue will return a ValueReference containing the string mapping value

func (*Discriminator) Hash

func (d *Discriminator) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the Discriminator object

type Example

type Example struct {
	Summary       low.NodeReference[string]
	Description   low.NodeReference[string]
	Value         low.NodeReference[*yaml.Node]
	ExternalValue low.NodeReference[string]
	Extensions    *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
	KeyNode       *yaml.Node
	RootNode      *yaml.Node
	*low.Reference
}

Example represents a low-level Example object as defined by OpenAPI 3+

v3 - https://spec.openapis.org/oas/v3.1.0#example-object

func (*Example) Build

func (ex *Example) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error

Build extracts extensions and example value

func (*Example) FindExtension

func (ex *Example) FindExtension(ext string) *low.ValueReference[*yaml.Node]

FindExtension returns a ValueReference containing the extension value, if found.

func (*Example) GetExtensions

func (ex *Example) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

GetExtensions will return Example extensions to satisfy the HasExtensions interface.

func (*Example) Hash

func (ex *Example) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the Discriminator object

type ExternalDoc

type ExternalDoc struct {
	Description low.NodeReference[string]
	URL         low.NodeReference[string]
	Extensions  *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
	KeyNode     *yaml.Node
	RootNode    *yaml.Node
	*low.Reference
}

ExternalDoc represents a low-level External Documentation object as defined by OpenAPI 2 and 3

Allows referencing an external resource for extended documentation.

v2 - https://swagger.io/specification/v2/#externalDocumentationObject
v3 - https://spec.openapis.org/oas/v3.1.0#external-documentation-object

func (*ExternalDoc) Build

func (ex *ExternalDoc) Build(_ context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error

Build will extract extensions from the ExternalDoc instance.

func (*ExternalDoc) FindExtension

func (ex *ExternalDoc) FindExtension(ext string) *low.ValueReference[*yaml.Node]

FindExtension returns a ValueReference containing the extension value, if found.

func (*ExternalDoc) GetExtensions

func (ex *ExternalDoc) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

GetExtensions returns all ExternalDoc extensions and satisfies the low.HasExtensions interface.

func (*ExternalDoc) Hash

func (ex *ExternalDoc) Hash() [32]byte

type Info

type Info struct {
	Title          low.NodeReference[string]
	Summary        low.NodeReference[string]
	Description    low.NodeReference[string]
	TermsOfService low.NodeReference[string]
	Contact        low.NodeReference[*Contact]
	License        low.NodeReference[*License]
	Version        low.NodeReference[string]
	Extensions     *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
	KeyNode        *yaml.Node
	RootNode       *yaml.Node
	*low.Reference
}

Info represents a low-level Info object as defined by both OpenAPI 2 and OpenAPI 3.

The object provides metadata about the API. The metadata MAY be used by the clients if needed, and MAY be presented in editing or documentation generation tools for convenience.

v2 - https://swagger.io/specification/v2/#infoObject
v3 - https://spec.openapis.org/oas/v3.1.0#info-object

func (*Info) Build

func (i *Info) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error

Build will extract out the Contact and Info objects from the supplied root node.

func (*Info) FindExtension

func (i *Info) FindExtension(ext string) *low.ValueReference[*yaml.Node]

FindExtension attempts to locate an extension with the supplied key

func (*Info) GetExtensions

func (i *Info) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

GetExtensions returns all extensions for Info

func (*Info) Hash

func (i *Info) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the Info object

type License

type License struct {
	Name       low.NodeReference[string]
	URL        low.NodeReference[string]
	Identifier low.NodeReference[string]
	KeyNode    *yaml.Node
	RootNode   *yaml.Node
	*low.Reference
}

License is a low-level representation of a License object as defined by OpenAPI 2 and OpenAPI 3

v2 - https://swagger.io/specification/v2/#licenseObject
v3 - https://spec.openapis.org/oas/v3.1.0#license-object

func (*License) Build

func (l *License) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error

Build out a license, complain if both a URL and identifier are present as they are mutually exclusive

func (*License) Hash

func (l *License) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the License object

type Schema

type Schema struct {
	// Reference to the '$schema' dialect setting (3.1 only)
	SchemaTypeRef low.NodeReference[string]

	// In versions 2 and 3.0, this ExclusiveMaximum can only be a boolean.
	ExclusiveMaximum low.NodeReference[*SchemaDynamicValue[bool, float64]]

	// In versions 2 and 3.0, this ExclusiveMinimum can only be a boolean.
	ExclusiveMinimum low.NodeReference[*SchemaDynamicValue[bool, float64]]

	// In versions 2 and 3.0, this Type is a single value, so array will only ever have one value
	// in version 3.1, Type can be multiple values
	Type low.NodeReference[SchemaDynamicValue[string, []low.ValueReference[string]]]

	// Schemas are resolved on demand using a SchemaProxy
	AllOf low.NodeReference[[]low.ValueReference[*SchemaProxy]]

	// Polymorphic Schemas are only available in version 3+
	OneOf         low.NodeReference[[]low.ValueReference[*SchemaProxy]]
	AnyOf         low.NodeReference[[]low.ValueReference[*SchemaProxy]]
	Discriminator low.NodeReference[*Discriminator]

	// in 3.1 examples can be an array (which is recommended)
	Examples low.NodeReference[[]low.ValueReference[*yaml.Node]]
	// in 3.1 PrefixItems provides tuple validation using prefixItems.
	PrefixItems low.NodeReference[[]low.ValueReference[*SchemaProxy]]
	// in 3.1 Contains is used by arrays and points to a Schema.
	Contains    low.NodeReference[*SchemaProxy]
	MinContains low.NodeReference[int64]
	MaxContains low.NodeReference[int64]

	// items can be a schema in 2.0, 3.0 and 3.1 or a bool in 3.1
	Items low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]

	// 3.1 only
	If                    low.NodeReference[*SchemaProxy]
	Else                  low.NodeReference[*SchemaProxy]
	Then                  low.NodeReference[*SchemaProxy]
	DependentSchemas      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]
	UnevaluatedItems      low.NodeReference[*SchemaProxy]
	UnevaluatedProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]
	Anchor                low.NodeReference[string]

	// Compatible with all versions
	Title                low.NodeReference[string]
	MultipleOf           low.NodeReference[float64]
	Maximum              low.NodeReference[float64]
	Minimum              low.NodeReference[float64]
	MaxLength            low.NodeReference[int64]
	MinLength            low.NodeReference[int64]
	Pattern              low.NodeReference[string]
	Format               low.NodeReference[string]
	MaxItems             low.NodeReference[int64]
	MinItems             low.NodeReference[int64]
	UniqueItems          low.NodeReference[bool]
	MaxProperties        low.NodeReference[int64]
	MinProperties        low.NodeReference[int64]
	Required             low.NodeReference[[]low.ValueReference[string]]
	Enum                 low.NodeReference[[]low.ValueReference[*yaml.Node]]
	Not                  low.NodeReference[*SchemaProxy]
	Properties           low.NodeReference[*orderedmap.Map[low.KeyReference[string], low.ValueReference[*SchemaProxy]]]
	AdditionalProperties low.NodeReference[*SchemaDynamicValue[*SchemaProxy, bool]]
	Description          low.NodeReference[string]
	ContentEncoding      low.NodeReference[string]
	ContentMediaType     low.NodeReference[string]
	Default              low.NodeReference[*yaml.Node]
	Const                low.NodeReference[*yaml.Node]
	Nullable             low.NodeReference[bool]
	ReadOnly             low.NodeReference[bool]
	WriteOnly            low.NodeReference[bool]
	XML                  low.NodeReference[*XML]
	ExternalDocs         low.NodeReference[*ExternalDoc]
	Example              low.NodeReference[*yaml.Node]
	Deprecated           low.NodeReference[bool]
	Extensions           *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

	// Parent Proxy refers back to the low level SchemaProxy that is proxying this schema.
	ParentProxy *SchemaProxy

	// Index is a reference to the SpecIndex that was used to build this schema.
	Index *index.SpecIndex
	*low.Reference
}

Schema represents a JSON Schema that support Swagger, OpenAPI 3 and OpenAPI 3.1

Until 3.1 OpenAPI had a strange relationship with JSON Schema. It's been a super-set/sub-set mix, which has been confusing. So, instead of building a bunch of different models, we have compressed all variations into a single model that makes it easy to support multiple spec types.

func (*Schema) Build

func (s *Schema) Build(ctx context.Context, root *yaml.Node, idx *index.SpecIndex) error

Build will perform a number of operations. Extraction of the following happens in this method:

  • Extensions
  • Type
  • ExclusiveMinimum and ExclusiveMaximum
  • Examples
  • AdditionalProperties
  • Discriminator
  • ExternalDocs
  • XML
  • Properties
  • AllOf, OneOf, AnyOf
  • Not
  • Items
  • PrefixItems
  • If
  • Else
  • Then
  • DependentSchemas
  • PatternProperties
  • PropertyNames
  • UnevaluatedItems
  • UnevaluatedProperties
  • Anchor

func (*Schema) FindDependentSchema

func (s *Schema) FindDependentSchema(name string) *low.ValueReference[*SchemaProxy]

FindDependentSchema will return a ValueReference pointer containing a SchemaProxy pointer from a dependent schema key name. if found (3.1+ only)

func (*Schema) FindPatternProperty

func (s *Schema) FindPatternProperty(name string) *low.ValueReference[*SchemaProxy]

FindPatternProperty will return a ValueReference pointer containing a SchemaProxy pointer from a pattern property key name. if found (3.1+ only)

func (*Schema) FindProperty

func (s *Schema) FindProperty(name string) *low.ValueReference[*SchemaProxy]

FindProperty will return a ValueReference pointer containing a SchemaProxy pointer from a property key name. if found

func (*Schema) GetExtensions

func (s *Schema) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

GetExtensions returns all extensions for Schema

func (*Schema) Hash

func (s *Schema) Hash() [32]byte

Hash will calculate a SHA256 hash from the values of the schema, This allows equality checking against Schemas defined inside an OpenAPI document. The only way to know if a schema has changed, is to hash it.

type SchemaDynamicValue

type SchemaDynamicValue[A any, B any] struct {
	N int // 0 == A, 1 == B
	A A
	B B
}

SchemaDynamicValue is used to hold multiple possible values for a schema property. There are two values, a left value (A) and a right value (B). The left value (A) is a 3.0 schema property value, the right value (B) is a 3.1 schema value.

OpenAPI 3.1 treats a Schema as a real JSON schema, which means some properties become incompatible, or others now support more than one primitive type or structure. The N value is a bit to make it each to know which value (A or B) is used, this prevents having to if/else on the value to determine which one is set.

func (*SchemaDynamicValue[A, B]) Hash

func (s *SchemaDynamicValue[A, B]) Hash() [32]byte

Hash will generate a stable hash of the SchemaDynamicValue

func (*SchemaDynamicValue[A, B]) IsA

func (s *SchemaDynamicValue[A, B]) IsA() bool

IsA will return true if the 'A' or left value is set. (OpenAPI 3)

func (*SchemaDynamicValue[A, B]) IsB

func (s *SchemaDynamicValue[A, B]) IsB() bool

IsB will return true if the 'B' or right value is set (OpenAPI 3.1)

type SchemaProxy

type SchemaProxy struct {
	low.Reference
	// contains filtered or unexported fields
}

SchemaProxy exists as a stub that will create a Schema once (and only once) the Schema() method is called.

Why use a Proxy design?

There are three reasons.

1. Circular References and Endless Loops.

JSON Schema allows for references to be used. This means references can loop around and create infinite recursive structures, These 'Circular references' technically mean a schema can NEVER be resolved, not without breaking the loop somewhere along the chain.

Polymorphism in the form of 'oneOf' and 'anyOf' in version 3+ only exacerbates the problem.

These circular traps can be discovered using the resolver, however it's still not enough to stop endless loops and endless goroutine spawning. A proxy design means that resolving occurs on demand and runs down a single level only. preventing any run-away loops.

2. Performance

Even without circular references, Polymorphism creates large additional resolving chains that take a long time and slow things down when building. By preventing recursion through every polymorphic item, building models is kept fast and snappy, which is desired for realtime processing of specs.

  • Q: Yeah, but, why not just use state to avoiding re-visiting seen polymorphic nodes?
  • A: It's slow, takes up memory and still has runaway potential in very, very long chains.

3. Short Circuit Errors.

Schemas are where things can get messy, mainly because the Schema standard changes between versions, and it's not actually JSONSchema until 3.1, so lots of times a bad schema will break parsing. Errors are only found when a schema is needed, so the rest of the document is parsed and ready to use.

func (*SchemaProxy) Build

func (sp *SchemaProxy) Build(ctx context.Context, key, value *yaml.Node, idx *index.SpecIndex) error

Build will prepare the SchemaProxy for rendering, it does not build the Schema, only sets up internal state. Key maybe nil if absent.

func (*SchemaProxy) GetBuildError

func (sp *SchemaProxy) GetBuildError() error

GetBuildError returns the build error that was set when Schema() was called. If Schema() has not been run, or there were no errors during build, then nil will be returned.

func (*SchemaProxy) GetContext

func (sp *SchemaProxy) GetContext() context.Context

GetKeyNode will return the yaml.Node pointer that is a key for value node.

func (*SchemaProxy) GetKeyNode

func (sp *SchemaProxy) GetKeyNode() *yaml.Node

GetKeyNode will return the yaml.Node pointer that is a key for value node.

func (*SchemaProxy) GetSchemaReferenceLocation

func (sp *SchemaProxy) GetSchemaReferenceLocation() *index.NodeOrigin

func (*SchemaProxy) GetValueNode

func (sp *SchemaProxy) GetValueNode() *yaml.Node

GetValueNode will return the yaml.Node pointer used by the proxy to generate the Schema.

func (*SchemaProxy) Hash

func (sp *SchemaProxy) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the SchemaProxy object (it will resolve it)

func (*SchemaProxy) Schema

func (sp *SchemaProxy) Schema() *Schema

Schema will first check if this SchemaProxy has already rendered the schema, and return the pre-rendered version first.

If this is the first run of Schema(), then the SchemaProxy will create a new Schema from the underlying yaml.Node. Once built out, the SchemaProxy will record that Schema as rendered and store it for later use, (this is what is we mean when we say 'pre-rendered').

Schema() then returns the newly created Schema.

If anything goes wrong during the build, then nothing is returned and the error that occurred can be retrieved by using GetBuildError()

type SecurityRequirement

type SecurityRequirement struct {
	Requirements             low.ValueReference[*orderedmap.Map[low.KeyReference[string], low.ValueReference[[]low.ValueReference[string]]]]
	KeyNode                  *yaml.Node
	RootNode                 *yaml.Node
	ContainsEmptyRequirement bool // if a requirement is empty (this means it's optional)
	*low.Reference
}

SecurityRequirement is a low-level representation of a Swagger / OpenAPI 3 SecurityRequirement object.

SecurityRequirement lists the required security schemes to execute this operation. The object can have multiple security schemes declared in it which are all required (that is, there is a logical AND between the schemes).

The name used for each property MUST correspond to a security scheme declared in the Security Definitions

func (*SecurityRequirement) Build

func (s *SecurityRequirement) Build(_ context.Context, keyNode, root *yaml.Node, _ *index.SpecIndex) error

Build will extract security requirements from the node (the structure is odd, to be honest)

func (*SecurityRequirement) FindRequirement

func (s *SecurityRequirement) FindRequirement(name string) []low.ValueReference[string]

FindRequirement will attempt to locate a security requirement string from a supplied name.

func (*SecurityRequirement) GetKeys

func (s *SecurityRequirement) GetKeys() []string

GetKeys returns a string slice of all the keys used in the requirement.

func (*SecurityRequirement) Hash

func (s *SecurityRequirement) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the SecurityRequirement object

type Tag

type Tag struct {
	Name         low.NodeReference[string]
	Description  low.NodeReference[string]
	ExternalDocs low.NodeReference[*ExternalDoc]
	Extensions   *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
	KeyNode      *yaml.Node
	RootNode     *yaml.Node
	*low.Reference
}

Tag represents a low-level Tag instance that is backed by a low-level one.

Adds metadata to a single tag that is used by the Operation Object. It is not mandatory to have a Tag Object per tag defined in the Operation Object instances.

func (*Tag) Build

func (t *Tag) Build(ctx context.Context, keyNode, root *yaml.Node, idx *index.SpecIndex) error

Build will extract extensions and external docs for the Tag.

func (*Tag) FindExtension

func (t *Tag) FindExtension(ext string) *low.ValueReference[*yaml.Node]

FindExtension returns a ValueReference containing the extension value, if found.

func (*Tag) GetExtensions

func (t *Tag) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

GetExtensions returns all Tag extensions and satisfies the low.HasExtensions interface.

func (*Tag) Hash

func (t *Tag) Hash() [32]byte

Hash will return a consistent SHA256 Hash of the Info object

type XML

type XML struct {
	Name       low.NodeReference[string]
	Namespace  low.NodeReference[string]
	Prefix     low.NodeReference[string]
	Attribute  low.NodeReference[bool]
	Wrapped    low.NodeReference[bool]
	Extensions *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]
	*low.Reference
}

XML represents a low-level representation of an XML object defined by all versions of OpenAPI.

A metadata object that allows for more fine-tuned XML model definitions.

When using arrays, XML element names are not inferred (for singular/plural forms) and the name property SHOULD be used to add that information. See examples for expected behavior.

v2 - https://swagger.io/specification/v2/#xmlObject
v3 - https://swagger.io/specification/#xml-object

func (*XML) Build

func (x *XML) Build(root *yaml.Node, _ *index.SpecIndex) error

Build will extract extensions from the XML instance.

func (*XML) GetExtensions

func (x *XML) GetExtensions() *orderedmap.Map[low.KeyReference[string], low.ValueReference[*yaml.Node]]

GetExtensions returns all Tag extensions and satisfies the low.HasExtensions interface.

func (*XML) Hash

func (x *XML) Hash() [32]byte

Hash generates a SHA256 hash of the XML object using properties

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL