Skip to content

Commit

Permalink
Clean up component type generation
Browse files Browse the repository at this point in the history
Clean up generation of Go types from objects found under
the Component schemas, and add some tests for each kind
that we support.
  • Loading branch information
Marcin Romaszewicz committed Apr 19, 2019
1 parent 71c3f1f commit 52364d1
Show file tree
Hide file tree
Showing 9 changed files with 155 additions and 8 deletions.
2 changes: 2 additions & 0 deletions examples/petestore-expanded/api/petstore.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,9 +128,11 @@ func (w *ServerInterfaceWrapper) FindPetById(ctx echo.Context) error {
}

func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) {

wrapper := ServerInterfaceWrapper{
Handler: si,
}

router.GET("/pets", wrapper.FindPets)
router.POST("/pets", wrapper.AddPet)
router.DELETE("/pets/:id", wrapper.DeletePet)
Expand Down
78 changes: 78 additions & 0 deletions internal/test/components/components.gen.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// This is an autogenerated file, any edits which you make here will be lost!
package components

import (
"bytes"
"compress/gzip"
"encoding/base64"
"fmt"
"github.com/deepmap/oapi-codegen/pkg/runtime"
"github.com/getkin/kin-openapi/openapi3"
"strings"
)

// Type definition for component schema "SchemaObject"
type SchemaObject struct {
FirstName string `json:"firstName"`
Role string `json:"role"`
}

// Type definition for component parameter "ParameterObject"
type ParameterObject string

// Type definition for component response "ResponseObject"
type ResponseObject struct {
Field SchemaObject `json:"Field"`
}

// Type definition for component requestBodies "RequestBody"
type RequestBody struct {
Field SchemaObject `json:"Field"`
}

type ServerInterface interface {
}

type ServerInterfaceWrapper struct {
Handler ServerInterface
}

func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) {

}

// Base64 encoded, gzipped, json marshaled Swagger object
var swaggerSpec = []string{

"H4sIAAAAAAAC/9ySzU7rQAyFXyXyvcsoacUuO1ggseBHtDvUxTBxwdVkZmq7FVWVd0czSVsofQFYxXbs",
"75yjZA82dDF49CrQ7CEaNh0qcu6eDt3j6wqtppENXtHn0sToyBql4OuVBJ9mYt+xM5nEISIrYSbdEro2",
"Ff8Zl9DAv/qkWw9HUs/yc9Tq+xIY1xtibKF5GQmLNFb80Do6Q2eSuosIDYgy+Tfo02qLYpli8ggNmOKY",
"D0pI57DeIO+OYih6E9rR8/NxsPt1yQeGxODlEGZo/siXvC6EuuiwOIQswklsdJFA34z8yLIkFn0wHV7Q",
"LIGDu/TiLE3eKr+gFtku+WVIx44seskcn4Xg/m6e6Eqa8DBH0WKGvM3/5BZZhoTTalJN0mKI6E0kaOCq",
"mlRT6D8DAAD//9SMdbW0AwAA",
}

// Returns the Swagger specification corresponding to the generated code
// in this file.
func GetSwagger() (*openapi3.Swagger, error) {
zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
if err != nil {
return nil, fmt.Errorf("error base64 decoding spec: %s", err)
}
zr, err := gzip.NewReader(bytes.NewReader(zipped))
if err != nil {
return nil, fmt.Errorf("error decompressing spec: %s", err)
}
var buf bytes.Buffer
_, err = buf.ReadFrom(zr)
if err != nil {
return nil, fmt.Errorf("error decompressing spec: %s", err)
}

swagger, err := openapi3.NewSwaggerLoader().LoadSwaggerFromData(buf.Bytes())
if err != nil {
return nil, fmt.Errorf("error loading Swagger: %s", err)
}
return swagger, nil
}

56 changes: 56 additions & 0 deletions internal/test/components/components.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
openapi: "3.0.1"
info:
version: 1.0.0
title: Test Server
license:
name: MIT
components:
schemas:
SchemaObject:
properties:
role:
type: string
firstName:
type: string
required:
- role
- firstName
responses:
ResponseObject:
description: A simple response object
content:
application/json:
schema:
properties:
Field:
$ref: "#/components/schemas/SchemaObject"
required: [ Field ]
text/plain:
schema:
type: string
parameters:
ParameterObject:
description: a parameter
in: query
content:
application/json:
schema:
properties:
Field:
$ref: "#/components/schemas/SchemaObject"
required: [ Field ]
text/plain:
schema:
type: string
requestBodies:
RequestBody:
content:
application/json:
schema:
properties:
Field:
$ref: "#/components/schemas/SchemaObject"
required: [ Field ]
text/plain:
schema:
type: string
4 changes: 4 additions & 0 deletions internal/test/components/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package components

//go:generate sh -c "oapi-codegen --package=components components.yaml > components.gen.go"

2 changes: 2 additions & 0 deletions internal/test/parameters/parameters.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -536,9 +536,11 @@ func (w *ServerInterfaceWrapper) GetSimplePrimitive(ctx echo.Context) error {
}

func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) {

wrapper := ServerInterfaceWrapper{
Handler: si,
}

router.GET("/contentObject/:param", wrapper.GetContentObject)
router.GET("/header", wrapper.GetHeader)
router.GET("/labelExplodeArray/:param", wrapper.GetLabelExplodeArray)
Expand Down
9 changes: 5 additions & 4 deletions pkg/codegen/codegen.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ func GenerateServer(swagger *openapi3.Swagger, packageName string) (string, erro
"compress/gzip",
"encoding/base64",
"fmt",
"github.com/labstack/echo/v4",
"github.com/getkin/kin-openapi/openapi3",
"github.com/deepmap/oapi-codegen/pkg/runtime",
"strings",
Expand All @@ -85,8 +84,7 @@ func GenerateServer(swagger *openapi3.Swagger, packageName string) (string, erro
var buf bytes.Buffer
w := bufio.NewWriter(&buf)

// Now that we've generated the types, we know whether we reference time.Time,
// so add that to import list, and generate all the imports.
// Based on module prefixes, figure out which optional imports are required.
for _, str := range []string{schemasOut, paramsOut, responsesOut, bodiesOut,
handlersOut, inlinedSpec} {
if strings.Contains(str, "time.Time") {
Expand All @@ -101,6 +99,9 @@ func GenerateServer(swagger *openapi3.Swagger, packageName string) (string, erro
if strings.Contains(str, "json.") {
imports = append(imports, "encoding/json")
}
if strings.Contains(str, "echo.") {
imports = append(imports, "github.com/labstack/echo/v4")
}
}

importsOut, err := GenerateImports(t, imports, packageName)
Expand Down Expand Up @@ -207,7 +208,7 @@ func GenerateTypesForParameters(t *template.Template, params map[string]*openapi
})
} else {
// The parameter is defined inline
goType, err := schemaToGoType(paramOrRef.Value.Schema, true)
goType, err := paramToGoType(paramOrRef.Value)
if err != nil {
return "", fmt.Errorf("error generating Go type for schema in parameter %s: %s",
paramName, err)
Expand Down
2 changes: 2 additions & 0 deletions pkg/codegen/templates/register.tmpl
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) {
{{if .}}
wrapper := ServerInterfaceWrapper{
Handler: si,
}
{{end}}
{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
{{end}}
}
2 changes: 2 additions & 0 deletions pkg/codegen/templates/templates.gen.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ type {{.TypeName}} {{.TypeDef}}
{{end}}
`,
"register.tmpl": `func RegisterHandlers(router runtime.EchoRouter, si ServerInterface) {
{{if .}}
wrapper := ServerInterfaceWrapper{
Handler: si,
}
{{end}}
{{range .}}router.{{.Method}}("{{.Path | swaggerUriToEchoUri}}", wrapper.{{.OperationId}})
{{end}}
}
Expand Down
8 changes: 4 additions & 4 deletions pkg/codegen/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,16 +168,16 @@ func StringInArray(str string, array []string) bool {
// #/components/schemas/Foo -> Foo
// #/components/parameters/Bar -> Bar
// #/components/responses/Baz -> Baz
// Remote references (document.json#/Foo) are not yet supported
// URL references (http://deepmap.com/schemas/document.json#Foo) are not yet
// Remote components (document.json#/Foo) are not yet supported
// URL components (http://deepmap.com/schemas/document.json#Foo) are not yet
// supported
// We only support flat references for now, so no components in a schema under
// We only support flat components for now, so no components in a schema under
// components.

func RefPathToGoType(refPath string) (string, error) {
pathParts := strings.Split(refPath, "/")
if pathParts[0] != "#" {
return "", errors.New("Only local document references are supported")
return "", errors.New("Only local document components are supported")
}
if len(pathParts) != 4 {
return "", errors.New("Parameter nesting is deeper than supported")
Expand Down

0 comments on commit 52364d1

Please sign in to comment.