go: vendor the oapi-codegen cmd
See the comment in tools.go, I cannot fully explain what's happening here. Somehow, Go 1.14 wants to use the vendored version of oapi-codegen but without this file, oapi-codegen isn't vendored so the generation fails. Signed-off-by: Ondřej Budai <ondrej@budai.cz>
This commit is contained in:
parent
1a3cbb282a
commit
2241a8d9ed
75 changed files with 11211 additions and 0 deletions
790
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/operations.go
generated
vendored
Normal file
790
vendor/github.com/deepmap/oapi-codegen/pkg/codegen/operations.go
generated
vendored
Normal file
|
|
@ -0,0 +1,790 @@
|
|||
// Copyright 2019 DeepMap, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package codegen
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"fmt"
|
||||
"strings"
|
||||
"text/template"
|
||||
"unicode"
|
||||
|
||||
"github.com/getkin/kin-openapi/openapi3"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type ParameterDefinition struct {
|
||||
ParamName string // The original json parameter name, eg param_name
|
||||
In string // Where the parameter is defined - path, header, cookie, query
|
||||
Required bool // Is this a required parameter?
|
||||
Spec *openapi3.Parameter
|
||||
Schema Schema
|
||||
}
|
||||
|
||||
// This function is here as an adapter after a large refactoring so that I don't
|
||||
// have to update all the templates. It returns the type definition for a parameter,
|
||||
// without the leading '*' for optional ones.
|
||||
func (pd ParameterDefinition) TypeDef() string {
|
||||
typeDecl := pd.Schema.TypeDecl()
|
||||
return typeDecl
|
||||
}
|
||||
|
||||
// Generate the JSON annotation to map GoType to json type name. If Parameter
|
||||
// Foo is marshaled to json as "foo", this will create the annotation
|
||||
// 'json:"foo"'
|
||||
func (pd *ParameterDefinition) JsonTag() string {
|
||||
if pd.Required {
|
||||
return fmt.Sprintf("`json:\"%s\"`", pd.ParamName)
|
||||
} else {
|
||||
return fmt.Sprintf("`json:\"%s,omitempty\"`", pd.ParamName)
|
||||
}
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) IsJson() bool {
|
||||
p := pd.Spec
|
||||
if len(p.Content) == 1 {
|
||||
_, found := p.Content["application/json"]
|
||||
return found
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) IsPassThrough() bool {
|
||||
p := pd.Spec
|
||||
if len(p.Content) > 1 {
|
||||
return true
|
||||
}
|
||||
if len(p.Content) == 1 {
|
||||
return !pd.IsJson()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) IsStyled() bool {
|
||||
p := pd.Spec
|
||||
return p.Schema != nil
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) Style() string {
|
||||
style := pd.Spec.Style
|
||||
if style == "" {
|
||||
in := pd.Spec.In
|
||||
switch in {
|
||||
case "path", "header":
|
||||
return "simple"
|
||||
case "query", "cookie":
|
||||
return "form"
|
||||
default:
|
||||
panic("unknown parameter format")
|
||||
}
|
||||
}
|
||||
return style
|
||||
}
|
||||
|
||||
func (pd *ParameterDefinition) Explode() bool {
|
||||
if pd.Spec.Explode == nil {
|
||||
in := pd.Spec.In
|
||||
switch in {
|
||||
case "path", "header":
|
||||
return false
|
||||
case "query", "cookie":
|
||||
return true
|
||||
default:
|
||||
panic("unknown parameter format")
|
||||
}
|
||||
}
|
||||
return *pd.Spec.Explode
|
||||
}
|
||||
|
||||
func (pd ParameterDefinition) GoVariableName() string {
|
||||
name := LowercaseFirstCharacter(pd.GoName())
|
||||
if IsGoKeyword(name) {
|
||||
name = "p" + UppercaseFirstCharacter(name)
|
||||
}
|
||||
if unicode.IsNumber([]rune(name)[0]) {
|
||||
name = "n" + name
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (pd ParameterDefinition) GoName() string {
|
||||
return ToCamelCase(pd.ParamName)
|
||||
}
|
||||
|
||||
func (pd ParameterDefinition) IndirectOptional() bool {
|
||||
return !pd.Required && !pd.Schema.SkipOptionalPointer
|
||||
}
|
||||
|
||||
type ParameterDefinitions []ParameterDefinition
|
||||
|
||||
func (p ParameterDefinitions) FindByName(name string) *ParameterDefinition {
|
||||
for _, param := range p {
|
||||
if param.ParamName == name {
|
||||
return ¶m
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// This function walks the given parameters dictionary, and generates the above
|
||||
// descriptors into a flat list. This makes it a lot easier to traverse the
|
||||
// data in the template engine.
|
||||
func DescribeParameters(params openapi3.Parameters, path []string) ([]ParameterDefinition, error) {
|
||||
outParams := make([]ParameterDefinition, 0)
|
||||
for _, paramOrRef := range params {
|
||||
param := paramOrRef.Value
|
||||
|
||||
goType, err := paramToGoType(param, append(path, param.Name))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating type for param (%s): %s",
|
||||
param.Name, err)
|
||||
}
|
||||
|
||||
pd := ParameterDefinition{
|
||||
ParamName: param.Name,
|
||||
In: param.In,
|
||||
Required: param.Required,
|
||||
Spec: param,
|
||||
Schema: goType,
|
||||
}
|
||||
|
||||
// If this is a reference to a predefined type, simply use the reference
|
||||
// name as the type. $ref: "#/components/schemas/custom_type" becomes
|
||||
// "CustomType".
|
||||
if paramOrRef.Ref != "" {
|
||||
goType, err := RefPathToGoType(paramOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error dereferencing (%s) for param (%s): %s",
|
||||
paramOrRef.Ref, param.Name, err)
|
||||
}
|
||||
pd.Schema.GoType = goType
|
||||
}
|
||||
outParams = append(outParams, pd)
|
||||
}
|
||||
return outParams, nil
|
||||
}
|
||||
|
||||
type SecurityDefinition struct {
|
||||
ProviderName string
|
||||
Scopes []string
|
||||
}
|
||||
|
||||
func DescribeSecurityDefinition(securityRequirements openapi3.SecurityRequirements) []SecurityDefinition {
|
||||
outDefs := make([]SecurityDefinition, 0)
|
||||
|
||||
for _, sr := range securityRequirements {
|
||||
for k, v := range sr {
|
||||
outDefs = append(outDefs, SecurityDefinition{ProviderName: k, Scopes: v})
|
||||
}
|
||||
}
|
||||
|
||||
return outDefs
|
||||
}
|
||||
|
||||
// This structure describes an Operation
|
||||
type OperationDefinition struct {
|
||||
OperationId string // The operation_id description from Swagger, used to generate function names
|
||||
|
||||
PathParams []ParameterDefinition // Parameters in the path, eg, /path/:param
|
||||
HeaderParams []ParameterDefinition // Parameters in HTTP headers
|
||||
QueryParams []ParameterDefinition // Parameters in the query, /path?param
|
||||
CookieParams []ParameterDefinition // Parameters in cookies
|
||||
TypeDefinitions []TypeDefinition // These are all the types we need to define for this operation
|
||||
SecurityDefinitions []SecurityDefinition // These are the security providers
|
||||
BodyRequired bool
|
||||
Bodies []RequestBodyDefinition // The list of bodies for which to generate handlers.
|
||||
Summary string // Summary string from Swagger, used to generate a comment
|
||||
Method string // GET, POST, DELETE, etc.
|
||||
Path string // The Swagger path for the operation, like /resource/{id}
|
||||
Spec *openapi3.Operation
|
||||
}
|
||||
|
||||
// Returns the list of all parameters except Path parameters. Path parameters
|
||||
// are handled differently from the rest, since they're mandatory.
|
||||
func (o *OperationDefinition) Params() []ParameterDefinition {
|
||||
result := append(o.QueryParams, o.HeaderParams...)
|
||||
result = append(result, o.CookieParams...)
|
||||
return result
|
||||
}
|
||||
|
||||
// Returns all parameters
|
||||
func (o *OperationDefinition) AllParams() []ParameterDefinition {
|
||||
result := append(o.QueryParams, o.HeaderParams...)
|
||||
result = append(result, o.CookieParams...)
|
||||
result = append(result, o.PathParams...)
|
||||
return result
|
||||
}
|
||||
|
||||
// If we have parameters other than path parameters, they're bundled into an
|
||||
// object. Returns true if we have any of those. This is used from the template
|
||||
// engine.
|
||||
func (o *OperationDefinition) RequiresParamObject() bool {
|
||||
return len(o.Params()) > 0
|
||||
}
|
||||
|
||||
// This is called by the template engine to determine whether to generate body
|
||||
// marshaling code on the client. This is true for all body types, whether or
|
||||
// not we generate types for them.
|
||||
func (o *OperationDefinition) HasBody() bool {
|
||||
return o.Spec.RequestBody != nil
|
||||
}
|
||||
|
||||
// This returns the Operations summary as a multi line comment
|
||||
func (o *OperationDefinition) SummaryAsComment() string {
|
||||
if o.Summary == "" {
|
||||
return ""
|
||||
}
|
||||
trimmed := strings.TrimSuffix(o.Summary, "\n")
|
||||
parts := strings.Split(trimmed, "\n")
|
||||
for i, p := range parts {
|
||||
parts[i] = "// " + p
|
||||
}
|
||||
return strings.Join(parts, "\n")
|
||||
}
|
||||
|
||||
// Produces a list of type definitions for a given Operation for the response
|
||||
// types which we know how to parse. These will be turned into fields on a
|
||||
// response object for automatic deserialization of responses in the generated
|
||||
// Client code. See "client-with-responses.tmpl".
|
||||
func (o *OperationDefinition) GetResponseTypeDefinitions() ([]TypeDefinition, error) {
|
||||
var tds []TypeDefinition
|
||||
|
||||
responses := o.Spec.Responses
|
||||
sortedResponsesKeys := SortedResponsesKeys(responses)
|
||||
for _, responseName := range sortedResponsesKeys {
|
||||
responseRef := responses[responseName]
|
||||
|
||||
// We can only generate a type if we have a value:
|
||||
if responseRef.Value != nil {
|
||||
sortedContentKeys := SortedContentKeys(responseRef.Value.Content)
|
||||
for _, contentTypeName := range sortedContentKeys {
|
||||
contentType := responseRef.Value.Content[contentTypeName]
|
||||
// We can only generate a type if we have a schema:
|
||||
if contentType.Schema != nil {
|
||||
responseSchema, err := GenerateGoSchema(contentType.Schema, []string{responseName})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("Unable to determine Go type for %s.%s", o.OperationId, contentTypeName))
|
||||
}
|
||||
|
||||
var typeName string
|
||||
switch {
|
||||
case StringInArray(contentTypeName, contentTypesJSON):
|
||||
typeName = fmt.Sprintf("JSON%s", ToCamelCase(responseName))
|
||||
// YAML:
|
||||
case StringInArray(contentTypeName, contentTypesYAML):
|
||||
typeName = fmt.Sprintf("YAML%s", ToCamelCase(responseName))
|
||||
// XML:
|
||||
case StringInArray(contentTypeName, contentTypesXML):
|
||||
typeName = fmt.Sprintf("XML%s", ToCamelCase(responseName))
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
td := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
Schema: responseSchema,
|
||||
ResponseName: responseName,
|
||||
}
|
||||
if contentType.Schema.Ref != "" {
|
||||
refType, err := RefPathToGoType(contentType.Schema.Ref)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error dereferencing response Ref")
|
||||
}
|
||||
td.Schema.RefType = refType
|
||||
}
|
||||
tds = append(tds, td)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return tds, nil
|
||||
}
|
||||
|
||||
// This describes a request body
|
||||
type RequestBodyDefinition struct {
|
||||
// Is this body required, or optional?
|
||||
Required bool
|
||||
|
||||
// This is the schema describing this body
|
||||
Schema Schema
|
||||
|
||||
// When we generate type names, we need a Tag for it, such as JSON, in
|
||||
// which case we will produce "JSONBody".
|
||||
NameTag string
|
||||
|
||||
// This is the content type corresponding to the body, eg, application/json
|
||||
ContentType string
|
||||
|
||||
// Whether this is the default body type. For an operation named OpFoo, we
|
||||
// will not add suffixes like OpFooJSONBody for this one.
|
||||
Default bool
|
||||
}
|
||||
|
||||
// Returns the Go type definition for a request body
|
||||
func (r RequestBodyDefinition) TypeDef() string {
|
||||
return r.Schema.TypeDecl()
|
||||
}
|
||||
|
||||
// Returns whether the body is a custom inline type, or pre-defined. This is
|
||||
// poorly named, but it's here for compatibility reasons post-refactoring
|
||||
// TODO: clean up the templates code, it can be simpler.
|
||||
func (r RequestBodyDefinition) CustomType() bool {
|
||||
return r.Schema.RefType == ""
|
||||
}
|
||||
|
||||
// When we're generating multiple functions which relate to request bodies,
|
||||
// this generates the suffix. Such as Operation DoFoo would be suffixed with
|
||||
// DoFooWithXMLBody.
|
||||
func (r RequestBodyDefinition) Suffix() string {
|
||||
// The default response is never suffixed.
|
||||
if r.Default {
|
||||
return ""
|
||||
}
|
||||
return "With" + r.NameTag + "Body"
|
||||
}
|
||||
|
||||
// This function returns the subset of the specified parameters which are of the
|
||||
// specified type.
|
||||
func FilterParameterDefinitionByType(params []ParameterDefinition, in string) []ParameterDefinition {
|
||||
var out []ParameterDefinition
|
||||
for _, p := range params {
|
||||
if p.In == in {
|
||||
out = append(out, p)
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// OperationDefinitions returns all operations for a swagger definition.
|
||||
func OperationDefinitions(swagger *openapi3.Swagger) ([]OperationDefinition, error) {
|
||||
var operations []OperationDefinition
|
||||
|
||||
for _, requestPath := range SortedPathsKeys(swagger.Paths) {
|
||||
pathItem := swagger.Paths[requestPath]
|
||||
// These are parameters defined for all methods on a given path. They
|
||||
// are shared by all methods.
|
||||
globalParams, err := DescribeParameters(pathItem.Parameters, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing global parameters for %s: %s",
|
||||
requestPath, err)
|
||||
}
|
||||
|
||||
// Each path can have a number of operations, POST, GET, OPTIONS, etc.
|
||||
pathOps := pathItem.Operations()
|
||||
for _, opName := range SortedOperationsKeys(pathOps) {
|
||||
op := pathOps[opName]
|
||||
// We rely on OperationID to generate function names, it's required
|
||||
if op.OperationID == "" {
|
||||
op.OperationID, err = generateDefaultOperationID(opName, requestPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error generating default OperationID for %s/%s: %s",
|
||||
opName, requestPath, err)
|
||||
}
|
||||
op.OperationID = op.OperationID
|
||||
} else {
|
||||
op.OperationID = ToCamelCase(op.OperationID)
|
||||
}
|
||||
|
||||
// These are parameters defined for the specific path method that
|
||||
// we're iterating over.
|
||||
localParams, err := DescribeParameters(op.Parameters, []string{op.OperationID + "Params"})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error describing global parameters for %s/%s: %s",
|
||||
opName, requestPath, err)
|
||||
}
|
||||
// All the parameters required by a handler are the union of the
|
||||
// global parameters and the local parameters.
|
||||
allParams := append(globalParams, localParams...)
|
||||
|
||||
// Order the path parameters to match the order as specified in
|
||||
// the path, not in the swagger spec, and validate that the parameter
|
||||
// names match, as downstream code depends on that.
|
||||
pathParams := FilterParameterDefinitionByType(allParams, "path")
|
||||
pathParams, err = SortParamsByPath(requestPath, pathParams)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bodyDefinitions, typeDefinitions, err := GenerateBodyDefinitions(op.OperationID, op.RequestBody)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "error generating body definitions")
|
||||
}
|
||||
|
||||
opDef := OperationDefinition{
|
||||
PathParams: pathParams,
|
||||
HeaderParams: FilterParameterDefinitionByType(allParams, "header"),
|
||||
QueryParams: FilterParameterDefinitionByType(allParams, "query"),
|
||||
CookieParams: FilterParameterDefinitionByType(allParams, "cookie"),
|
||||
OperationId: ToCamelCase(op.OperationID),
|
||||
// Replace newlines in summary.
|
||||
Summary: op.Summary,
|
||||
Method: opName,
|
||||
Path: requestPath,
|
||||
Spec: op,
|
||||
Bodies: bodyDefinitions,
|
||||
TypeDefinitions: typeDefinitions,
|
||||
}
|
||||
|
||||
// check for overrides of SecurityDefinitions.
|
||||
// See: "Step 2. Applying security:" from the spec:
|
||||
// https://swagger.io/docs/specification/authentication/
|
||||
if op.Security != nil {
|
||||
opDef.SecurityDefinitions = DescribeSecurityDefinition(*op.Security)
|
||||
} else {
|
||||
// use global securityDefinitions
|
||||
// globalSecurityDefinitions contains the top-level securityDefinitions.
|
||||
// They are the default securityPermissions which are injected into each
|
||||
// path, except for the case where a path explicitly overrides them.
|
||||
opDef.SecurityDefinitions = DescribeSecurityDefinition(swagger.Security)
|
||||
|
||||
}
|
||||
|
||||
if op.RequestBody != nil {
|
||||
opDef.BodyRequired = op.RequestBody.Value.Required
|
||||
}
|
||||
|
||||
// Generate all the type definitions needed for this operation
|
||||
opDef.TypeDefinitions = append(opDef.TypeDefinitions, GenerateTypeDefsForOperation(opDef)...)
|
||||
|
||||
operations = append(operations, opDef)
|
||||
}
|
||||
}
|
||||
return operations, nil
|
||||
}
|
||||
|
||||
func generateDefaultOperationID(opName string, requestPath string) (string, error) {
|
||||
var operationId string = strings.ToLower(opName)
|
||||
|
||||
if opName == "" {
|
||||
return "", fmt.Errorf("operation name cannot be an empty string")
|
||||
}
|
||||
|
||||
if requestPath == "" {
|
||||
return "", fmt.Errorf("request path cannot be an empty string")
|
||||
}
|
||||
|
||||
for _, part := range strings.Split(requestPath, "/") {
|
||||
if part != "" {
|
||||
operationId = operationId + "-" + part
|
||||
}
|
||||
}
|
||||
|
||||
return ToCamelCase(operationId), nil
|
||||
}
|
||||
|
||||
// This function turns the Swagger body definitions into a list of our body
|
||||
// definitions which will be used for code generation.
|
||||
func GenerateBodyDefinitions(operationID string, bodyOrRef *openapi3.RequestBodyRef) ([]RequestBodyDefinition, []TypeDefinition, error) {
|
||||
if bodyOrRef == nil {
|
||||
return nil, nil, nil
|
||||
}
|
||||
body := bodyOrRef.Value
|
||||
|
||||
var bodyDefinitions []RequestBodyDefinition
|
||||
var typeDefinitions []TypeDefinition
|
||||
|
||||
for contentType, content := range body.Content {
|
||||
var tag string
|
||||
var defaultBody bool
|
||||
|
||||
switch contentType {
|
||||
case "application/json":
|
||||
tag = "JSON"
|
||||
defaultBody = true
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
bodyTypeName := operationID + tag + "Body"
|
||||
bodySchema, err := GenerateGoSchema(content.Schema, []string{bodyTypeName})
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "error generating request body definition")
|
||||
}
|
||||
|
||||
// If the body is a pre-defined type
|
||||
if bodyOrRef.Ref != "" {
|
||||
// Convert the reference path to Go type
|
||||
refType, err := RefPathToGoType(bodyOrRef.Ref)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, fmt.Sprintf("error turning reference (%s) into a Go type", bodyOrRef.Ref))
|
||||
}
|
||||
bodySchema.RefType = refType
|
||||
}
|
||||
|
||||
// If the request has a body, but it's not a user defined
|
||||
// type under #/components, we'll define a type for it, so
|
||||
// that we have an easy to use type for marshaling.
|
||||
if bodySchema.RefType == "" {
|
||||
td := TypeDefinition{
|
||||
TypeName: bodyTypeName,
|
||||
Schema: bodySchema,
|
||||
}
|
||||
typeDefinitions = append(typeDefinitions, td)
|
||||
// The body schema now is a reference to a type
|
||||
bodySchema.RefType = bodyTypeName
|
||||
}
|
||||
|
||||
bd := RequestBodyDefinition{
|
||||
Required: body.Required,
|
||||
Schema: bodySchema,
|
||||
NameTag: tag,
|
||||
ContentType: contentType,
|
||||
Default: defaultBody,
|
||||
}
|
||||
bodyDefinitions = append(bodyDefinitions, bd)
|
||||
}
|
||||
return bodyDefinitions, typeDefinitions, nil
|
||||
}
|
||||
|
||||
func GenerateTypeDefsForOperation(op OperationDefinition) []TypeDefinition {
|
||||
var typeDefs []TypeDefinition
|
||||
// Start with the params object itself
|
||||
if len(op.Params()) != 0 {
|
||||
typeDefs = append(typeDefs, GenerateParamsTypes(op)...)
|
||||
}
|
||||
|
||||
// Now, go through all the additional types we need to declare.
|
||||
for _, param := range op.AllParams() {
|
||||
typeDefs = append(typeDefs, param.Schema.GetAdditionalTypeDefs()...)
|
||||
}
|
||||
|
||||
for _, body := range op.Bodies {
|
||||
typeDefs = append(typeDefs, body.Schema.GetAdditionalTypeDefs()...)
|
||||
}
|
||||
return typeDefs
|
||||
}
|
||||
|
||||
// This defines the schema for a parameters definition object which encapsulates
|
||||
// all the query, header and cookie parameters for an operation.
|
||||
func GenerateParamsTypes(op OperationDefinition) []TypeDefinition {
|
||||
var typeDefs []TypeDefinition
|
||||
|
||||
objectParams := op.QueryParams
|
||||
objectParams = append(objectParams, op.HeaderParams...)
|
||||
objectParams = append(objectParams, op.CookieParams...)
|
||||
|
||||
typeName := op.OperationId + "Params"
|
||||
|
||||
s := Schema{}
|
||||
for _, param := range objectParams {
|
||||
pSchema := param.Schema
|
||||
if pSchema.HasAdditionalProperties {
|
||||
propRefName := strings.Join([]string{typeName, param.GoName()}, "_")
|
||||
pSchema.RefType = propRefName
|
||||
typeDefs = append(typeDefs, TypeDefinition{
|
||||
TypeName: propRefName,
|
||||
Schema: param.Schema,
|
||||
})
|
||||
}
|
||||
prop := Property{
|
||||
Description: param.Spec.Description,
|
||||
JsonFieldName: param.ParamName,
|
||||
Required: param.Required,
|
||||
Schema: pSchema,
|
||||
}
|
||||
s.Properties = append(s.Properties, prop)
|
||||
}
|
||||
|
||||
s.GoType = GenStructFromSchema(s)
|
||||
|
||||
td := TypeDefinition{
|
||||
TypeName: typeName,
|
||||
Schema: s,
|
||||
}
|
||||
return append(typeDefs, td)
|
||||
}
|
||||
|
||||
// Generates code for all types produced
|
||||
func GenerateTypesForOperations(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "param-types.tmpl", ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating types for params objects")
|
||||
}
|
||||
|
||||
err = t.ExecuteTemplate(w, "request-bodies.tmpl", ops)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating request bodies for operations")
|
||||
}
|
||||
|
||||
// Generate boiler plate for all additional types.
|
||||
var td []TypeDefinition
|
||||
for _, op := range ops {
|
||||
td = append(td, op.TypeDefinitions...)
|
||||
}
|
||||
|
||||
addProps, err := GenerateAdditionalPropertyBoilerplate(t, td)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties boilerplate for operations")
|
||||
}
|
||||
|
||||
_, err = w.WriteString("\n")
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties boilerplate for operations")
|
||||
}
|
||||
|
||||
_, err = w.WriteString(addProps)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating additional properties boilerplate for operations")
|
||||
}
|
||||
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for server interface")
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// GenerateChiServer This function generates all the go code for the ServerInterface as well as
|
||||
// all the wrapper functions around our handlers.
|
||||
func GenerateChiServer(t *template.Template, operations []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "chi-interface.tmpl", operations)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating server interface")
|
||||
}
|
||||
|
||||
err = t.ExecuteTemplate(w, "chi-middleware.tmpl", operations)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating server middleware")
|
||||
}
|
||||
|
||||
err = t.ExecuteTemplate(w, "chi-handler.tmpl", operations)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error generating server http handler")
|
||||
}
|
||||
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "error flushing output buffer for server")
|
||||
}
|
||||
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// GenerateEchoServer This function generates all the go code for the ServerInterface as well as
|
||||
// all the wrapper functions around our handlers.
|
||||
func GenerateEchoServer(t *template.Template, operations []OperationDefinition) (string, error) {
|
||||
si, err := GenerateServerInterface(t, operations)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating server types and interface: %s", err)
|
||||
}
|
||||
|
||||
wrappers, err := GenerateWrappers(t, operations)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating handler wrappers: %s", err)
|
||||
}
|
||||
|
||||
register, err := GenerateRegistration(t, operations)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Error generating handler registration: %s", err)
|
||||
}
|
||||
return strings.Join([]string{si, wrappers, register}, "\n"), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate the server interface
|
||||
func GenerateServerInterface(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "server-interface.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating server interface: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for server interface: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate all the wrappers which wrap our simple
|
||||
// interface functions and perform marshallin/unmarshalling from HTTP
|
||||
// request objects.
|
||||
func GenerateWrappers(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "wrappers.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating server interface: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for server interface: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate the function which registers our wrappers
|
||||
// as Echo path handlers.
|
||||
func GenerateRegistration(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "register.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating route registration: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for route registration: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// Uses the template engine to generate the function which registers our wrappers
|
||||
// as Echo path handlers.
|
||||
func GenerateClient(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "client.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating client bindings: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for client: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
|
||||
// This generates a client which extends the basic client which does response
|
||||
// unmarshaling.
|
||||
func GenerateClientWithResponses(t *template.Template, ops []OperationDefinition) (string, error) {
|
||||
var buf bytes.Buffer
|
||||
w := bufio.NewWriter(&buf)
|
||||
|
||||
err := t.ExecuteTemplate(w, "client-with-responses.tmpl", ops)
|
||||
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error generating client bindings: %s", err)
|
||||
}
|
||||
err = w.Flush()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error flushing output buffer for client: %s", err)
|
||||
}
|
||||
return buf.String(), nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue