262 lines
6.1 KiB
Go
262 lines
6.1 KiB
Go
package openapi // import "udico.de/uditaren/opier/openapi"
|
|
import (
|
|
"fmt"
|
|
"gopkg.in/yaml.v3"
|
|
"os"
|
|
"strings"
|
|
"unicode"
|
|
)
|
|
|
|
type OpenAPI struct {
|
|
Version string `yaml:"openapi"`
|
|
Info struct {
|
|
Title string
|
|
Version string
|
|
Description string
|
|
}
|
|
Paths map[string]*PathItem `yaml:"paths"`
|
|
|
|
Components *Components
|
|
}
|
|
|
|
func Load(fname string) (*OpenAPI, error) {
|
|
f, err := os.Open(fname)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
tRet := &OpenAPI{}
|
|
tY := yaml.NewDecoder(f)
|
|
err = tY.Decode(tRet)
|
|
return tRet, err
|
|
}
|
|
|
|
// PathItem 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.
|
|
type PathItem struct {
|
|
|
|
// Allows for an external definition of this path item. The referenced structure MUST be in the format of a
|
|
// PathItem Object. In case a PathItem Object field appears both in the defined object and the referenced object,
|
|
// the behavior is undefined.
|
|
Ref string `yaml:"$ref"`
|
|
|
|
// An optional, string summary, intended to apply to all operations in this path.
|
|
Summary string
|
|
|
|
// An optional, string description, intended to apply to all operations in this path. CommonMark syntax MAY be
|
|
// used for rich text representation.
|
|
Description string
|
|
|
|
Get *Operation
|
|
Put *Operation
|
|
Post *Operation
|
|
Delete *Operation
|
|
Options *Operation
|
|
Head *Operation
|
|
Patch *Operation
|
|
Trace *Operation
|
|
}
|
|
|
|
func (p PathItem) Operations() map[string]*Operation {
|
|
tRet := make(map[string]*Operation)
|
|
if p.Get != nil {
|
|
tRet["get"] = p.Get
|
|
}
|
|
if p.Put != nil {
|
|
tRet["put"] = p.Put
|
|
}
|
|
if p.Post != nil {
|
|
tRet["post"] = p.Post
|
|
}
|
|
if p.Delete != nil {
|
|
tRet["delete"] = p.Delete
|
|
}
|
|
if p.Options != nil {
|
|
tRet["options"] = p.Options
|
|
}
|
|
if p.Head != nil {
|
|
tRet["head"] = p.Head
|
|
}
|
|
if p.Patch != nil {
|
|
tRet["patch"] = p.Patch
|
|
}
|
|
if p.Trace != nil {
|
|
tRet["trace"] = p.Trace
|
|
}
|
|
return tRet
|
|
}
|
|
|
|
// Operation describes a single API operation on a path.
|
|
type Operation struct {
|
|
// A list of tags for API documentation control. Tags can be used for logical grouping of operations
|
|
// by resources or any other qualifier.
|
|
Tags []string
|
|
|
|
// A short summary of what the operation does.
|
|
Summary string
|
|
|
|
// A verbose explanation of the operation behavior. CommonMark syntax MAY be used for rich text representation.
|
|
Description string
|
|
|
|
// Additional external documentation for this operation.
|
|
//externalDocs
|
|
|
|
// Unique string used to identify the operation. The id MUST be unique among all operations described in the API.
|
|
// The operationId value is case-sensitive. Tools and libraries MAY use the operationId to uniquely identify an
|
|
// operation, therefore, it is RECOMMENDED to follow common programming naming conventions.
|
|
OperationId string `yaml:"operationId"`
|
|
|
|
//Parameters [] ...
|
|
// requestBodyesObject // required
|
|
// callba
|
|
// Responses Responscks
|
|
Deprecated bool
|
|
|
|
// A declaration of which security mechanisms can be used for this operation.
|
|
// 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. To make security optional, an empty security
|
|
// requirement ({}) can be included in the array. This definition overrides any declared top-level security.
|
|
// To remove a top-level security declaration, an empty array can be used.
|
|
Security []map[string][]string `yaml:"security"`
|
|
|
|
// An alternative server array to service this operation. If an alternative server object is specified at the Path
|
|
// Item Object or Root level, it will be overridden by this value.
|
|
// Servers
|
|
}
|
|
|
|
type ResponsesObject struct {
|
|
// ...
|
|
}
|
|
|
|
type Components struct {
|
|
//SecuritySchemas
|
|
//Responses map[string, ResponseObject]
|
|
Parameters map[string]Parameter
|
|
Schemas map[string]Schema
|
|
}
|
|
|
|
type ParameterLocation string
|
|
|
|
const (
|
|
QUERY ParameterLocation = "query"
|
|
HEAD = "header"
|
|
PATH = "path"
|
|
COOKIE = "cookie"
|
|
)
|
|
|
|
type Parameter struct {
|
|
|
|
// only if this a reference object instead of a parameter obect
|
|
Ref string `yaml:"$ref"`
|
|
|
|
Name string
|
|
In ParameterLocation
|
|
Description string
|
|
Required bool
|
|
Deprecated bool
|
|
AllowEmptyValue bool `yaml:"allowEmptyValue"`
|
|
|
|
///--- either
|
|
|
|
Style string
|
|
Explode bool
|
|
AllowReserved bool `yaml:"allowReserved"`
|
|
Schema *Schema
|
|
// example
|
|
// examples
|
|
|
|
///--- or
|
|
Content map[string]*MediaType
|
|
}
|
|
|
|
type Schema struct {
|
|
// may be a schema reference:
|
|
Ref string `yaml:"$ref"`
|
|
|
|
Type string
|
|
// when type==array:
|
|
Items *Schema
|
|
// when type==object
|
|
Properties map[string]*Schema
|
|
|
|
Format string
|
|
Minimum int
|
|
Maximum int
|
|
Default interface{}
|
|
|
|
Enum []interface{}
|
|
XEnumVarnames []string `yaml:"x-enum-varnames"`
|
|
|
|
Required []string
|
|
Description string
|
|
}
|
|
|
|
func (s Schema) TypeOrReference() string {
|
|
if s.Ref != "" {
|
|
return s.Ref
|
|
}
|
|
return s.Type
|
|
}
|
|
|
|
func (s Schema) GoType() string {
|
|
tRet := s.Type
|
|
if s.Ref != "" {
|
|
idx := strings.LastIndex(s.Ref, "/")
|
|
tRet = "*" + s.Ref[idx+1:]
|
|
} else {
|
|
switch s.Type {
|
|
case "integer":
|
|
tRet = "int"
|
|
case "boolean":
|
|
tRet = "bool"
|
|
case "array":
|
|
tRet = fmt.Sprintf("[]%v", s.Items.GoType())
|
|
}
|
|
}
|
|
return tRet
|
|
}
|
|
|
|
// EnumNames returns the String representations for this enums values and the length of the longest name as well.
|
|
func (s Schema) EnumNames() ([]string, int) {
|
|
tLen := 0
|
|
tRet := make([]string, len(s.Enum), len(s.Enum))
|
|
for k, v := range s.Enum {
|
|
tName := NormalizeName(fmt.Sprintf("%v", v))
|
|
if len(s.XEnumVarnames) == len(s.Enum) {
|
|
// read the desired enum name instead
|
|
tName = s.XEnumVarnames[k]
|
|
}
|
|
tRet[k] = tName
|
|
if len(tName) > tLen {
|
|
tLen = len(tName)
|
|
}
|
|
}
|
|
return tRet, tLen
|
|
}
|
|
|
|
type Referencable interface {
|
|
|
|
}
|
|
|
|
type MediaType struct {
|
|
|
|
}
|
|
|
|
func NormalizeName(aName string) string {
|
|
tRet := &strings.Builder{}
|
|
capitalizeNext := true
|
|
for _, rune := range aName {
|
|
if capitalizeNext {
|
|
tRet.WriteRune(unicode.ToUpper(rune))
|
|
capitalizeNext = false
|
|
} else {
|
|
if rune == '-' {
|
|
capitalizeNext = true
|
|
} else {
|
|
tRet.WriteRune(rune)
|
|
}
|
|
}
|
|
}
|
|
return tRet.String()
|
|
}
|