From 9494cfa8bbf4388522ade1eb2a19aad08fe422ef Mon Sep 17 00:00:00 2001 From: Pierre-Louis Pery Date: Mon, 25 Jul 2022 17:07:13 +0200 Subject: [PATCH] pr/tiehm/66 (#93) * proposal: add extension x-go-type-external for external type references * convert to x-go-type and allow for custom types in bodies * remove examples with x-go-type * introduce the import:[import-name] format to import by specified name without an alias * fix: schema imports were missing * add first testing * fix: old example Authored-by: tiehm --- README.md | 32 ++++- codegen/codegen.go | 42 ++++-- codegen/extension.go | 25 +++- codegen/extension_test.go | 12 +- codegen/operations.go | 17 ++- codegen/schema.go | 39 +++++- examples/petstore-expanded/api/petstore.go | 2 +- internal/test/schemas/schemas.gen.go | 145 +++++++++++++++++--- internal/test/schemas/schemas.yaml | 48 +++++++ internal/test/schemas/schemas_test.go | 12 ++ internal/test/schemas/types/alias/types.go | 3 + internal/test/schemas/types/normal/types.go | 3 + 12 files changed, 320 insertions(+), 60 deletions(-) create mode 100644 internal/test/schemas/schemas_test.go create mode 100644 internal/test/schemas/types/alias/types.go create mode 100644 internal/test/schemas/types/normal/types.go diff --git a/README.md b/README.md index 1eb0cf1e..de8292cb 100644 --- a/README.md +++ b/README.md @@ -107,8 +107,8 @@ takes as input `FindPetsParams`, which is defined as follows: ```go // Parameters object for FindPets type FindPetsParams struct { - Tags *[]string `json:"tags,omitempty"` - Limit *int32 `json:"limit,omitempty"` + Tags *[]string `json:"tags,omitempty"` + Limit *int32 `json:"limit,omitempty"` } ``` @@ -235,9 +235,31 @@ look through those tests for more usage examples. `goapi-gen` supports the following extended properties: - `x-go-type`: specifies Go type name. It allows you to specify the type name for a schema, and - will override any default value. This extended property isn't supported in all parts of - OpenAPI, so please refer to the spec as to where it's allowed. Swagger validation tools will - flag incorrect usage of this property. + will override any default value. When using this with external types the fields `type,import` are required while + `alias` is only needed if your import collides with any existing imports. **If no alias is given, the generator + assumes that the import name is the last word from the import path (github.com/example/time => time). This can produce + issues as some projects (like chi with /v5) have different import names than paths. To be sure, always declare an alias. + For those cases, please attach a `:[import-name]` to the path like `github.com/go-chi/chi/v5:chi`, this will then also be + imported as `chi.*` without the use of an alias.** + This extended property isn't supported in all parts of OpenAPI, so please refer to the spec as to where it's allowed. + Swagger validation tools will flag incorrect usage of this property. + + ```yaml + components: + schemas: + Object: + properties: + name: + type: string + x-go-type: MyCustomString + time: + type: integer + x-go-type: + type: MyCustomTime + import: github.com/example/time + alias: time2 + ``` + - `x-go-extra-tags`: adds extra Go field tags to the generated struct field. This is useful for interfacing with tag based ORM or validation libraries. The extra tags that are added are in addition to the regular json tags that are generated. If you specify your diff --git a/codegen/codegen.go b/codegen/codegen.go index 4b89c0f8..e01edeb8 100644 --- a/codegen/codegen.go +++ b/codegen/codegen.go @@ -131,14 +131,20 @@ func Generate(swagger *openapi3.T, packageName string, opts Options) (string, er } } + var finalCustomImports []string ops, err := OperationDefinitions(swagger) if err != nil { return "", fmt.Errorf("error creating operation definitions: %w", err) } + for _, op := range ops { + finalCustomImports = append(finalCustomImports, op.CustomImports...) + } + var typeDefinitions, constantDefinitions string + var customImports []string if opts.GenerateTypes { - typeDefinitions, err = GenerateTypeDefinitions(t, swagger, ops, opts.ExcludeSchemas) + typeDefinitions, customImports, err = GenerateTypeDefinitions(t, swagger, ops, opts.ExcludeSchemas) if err != nil { return "", fmt.Errorf("error generating type definitions: %w", err) } @@ -150,6 +156,9 @@ func Generate(swagger *openapi3.T, packageName string, opts Options) (string, er } + // TODO: check for exact double imports and merge them together with 1 alias, otherwise we might run into double imports under different names + finalCustomImports = append(finalCustomImports, customImports...) + var serverOut string if opts.GenerateServer { serverOut, err = GenerateChiServer(t, ops) @@ -170,6 +179,7 @@ func Generate(swagger *openapi3.T, packageName string, opts Options) (string, er w := bufio.NewWriter(&buf) externalImports := importMapping.GoImports() + externalImports = append(externalImports, finalCustomImports...) importsOut, err := GenerateImports(t, externalImports, packageName) if err != nil { return "", fmt.Errorf("error generating imports: %w", err) @@ -227,57 +237,65 @@ func Generate(swagger *openapi3.T, packageName string, opts Options) (string, er // GenerateTypeDefinitions produces the type definitions in ops and executes // the template. -func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.T, ops []OperationDefinition, excludeSchemas []string) (string, error) { +func GenerateTypeDefinitions(t *template.Template, swagger *openapi3.T, ops []OperationDefinition, excludeSchemas []string) (string, []string, error) { schemaTypes, err := GenerateTypesForSchemas(t, swagger.Components.Schemas, excludeSchemas) if err != nil { - return "", fmt.Errorf("error generating Go types for component schemas: %w", err) + return "", nil, fmt.Errorf("error generating Go types for component schemas: %w", err) } paramTypes, err := GenerateTypesForParameters(t, swagger.Components.Parameters) if err != nil { - return "", fmt.Errorf("error generating Go types for component parameters: %w", err) + return "", nil, fmt.Errorf("error generating Go types for component parameters: %w", err) } allTypes := append(schemaTypes, paramTypes...) responseTypes, err := GenerateTypesForResponses(t, swagger.Components.Responses) if err != nil { - return "", fmt.Errorf("error generating Go types for component responses: %w", err) + return "", nil, fmt.Errorf("error generating Go types for component responses: %w", err) } allTypes = append(allTypes, responseTypes...) bodyTypes, err := GenerateTypesForRequestBodies(t, swagger.Components.RequestBodies) if err != nil { - return "", fmt.Errorf("error generating Go types for component request bodies: %w", err) + return "", nil, fmt.Errorf("error generating Go types for component request bodies: %w", err) } allTypes = append(allTypes, bodyTypes...) paramTypesOut, err := GenerateTypesForOperations(t, ops) if err != nil { - return "", fmt.Errorf("error generating Go types for component request bodies: %w", err) + return "", nil, fmt.Errorf("error generating Go types for component request bodies: %w", err) } enumsOut, err := GenerateEnums(t, allTypes) if err != nil { - return "", fmt.Errorf("error generating code for type enums: %w", err) + return "", nil, fmt.Errorf("error generating code for type enums: %w", err) } enumTypesOut, err := GenerateEnumTypes(t, allTypes) if err != nil { - return "", fmt.Errorf("error generating code for enum type definitions: %w", err) + return "", nil, fmt.Errorf("error generating code for enum type definitions: %w", err) } typesOut, err := GenerateTypes(t, allTypes) if err != nil { - return "", fmt.Errorf("error generating code for type definitions: %w", err) + return "", nil, fmt.Errorf("error generating code for type definitions: %w", err) } allOfBoilerplate, err := GenerateAdditionalPropertyBoilerplate(t, allTypes) if err != nil { - return "", fmt.Errorf("error generating allOf boilerplate: %w", err) + return "", nil, fmt.Errorf("error generating allOf boilerplate: %w", err) + } + + var customImports []string + for _, allType := range allTypes { + customImports = append(customImports, allType.Schema.CustomImports...) + for _, prop := range allType.Schema.Properties { + customImports = append(customImports, prop.Schema.CustomImports...) + } } typeDefinitions := enumsOut + typesOut + enumTypesOut + paramTypesOut + allOfBoilerplate - return typeDefinitions, nil + return typeDefinitions, customImports, nil } // GenerateConstants creates operation ids, context keys, paths, etc. to be diff --git a/codegen/extension.go b/codegen/extension.go index f558d847..beb159cf 100644 --- a/codegen/extension.go +++ b/codegen/extension.go @@ -14,10 +14,29 @@ const ( extMiddlewares = "x-go-middlewares" ) -func extTypeName(extPropValue interface{}) (string, error) { +type extImportPathDetails struct { + Import string `json:"import"` + Alias string `json:"alias"` + Type string `json:"type"` +} + + +func extImportPath(extPropValue interface{}) (extImportPathDetails, error) { + var details extImportPathDetails + raw, ok := extPropValue.(json.RawMessage) + if !ok { + return details, fmt.Errorf("failed to convert type: %T", extPropValue) + } + var name string - err := extParseAny(extPropValue, &name) - return name, err + if err := json.Unmarshal(raw, &name); err == nil { + details.Type = name + return details, nil + } + + var path extImportPathDetails + err := extParseAny(extPropValue, &path) + return path, err } func extExtraTags(extPropValue interface{}) (map[string]string, error) { diff --git a/codegen/extension_test.go b/codegen/extension_test.go index 64681a60..7f9cd8d1 100644 --- a/codegen/extension_test.go +++ b/codegen/extension_test.go @@ -7,38 +7,38 @@ import ( "github.com/stretchr/testify/assert" ) -func Test_extTypeName(t *testing.T) { +func Test_extImportPath(t *testing.T) { type args struct { extPropValue interface{} } tests := []struct { name string args args - want string + want extImportPathDetails wantErr bool }{ { name: "success", args: args{json.RawMessage(`"uint64"`)}, - want: "uint64", + want: extImportPathDetails{Type: "uint64"}, wantErr: false, }, { name: "type conversion error", args: args{nil}, - want: "", + want: extImportPathDetails{}, wantErr: true, }, { name: "json unmarshal error", args: args{json.RawMessage("invalid json format")}, - want: "", + want: extImportPathDetails{}, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := extTypeName(tt.args.extPropValue) + got, err := extImportPath(tt.args.extPropValue) if tt.wantErr { assert.Error(t, err) return diff --git a/codegen/operations.go b/codegen/operations.go index 4562286a..2c6a7fd3 100644 --- a/codegen/operations.go +++ b/codegen/operations.go @@ -211,6 +211,7 @@ func DescribeSecurityDefinition(srs openapi3.SecurityRequirements) []SecurityDef type OperationDefinition struct { OperationID string // The operation_id description from Swagger, used to generate function names + CustomImports []string // Custom needed imports due to parameters being of external types PathParams []ParameterDefinition // Parameters in the path, eg, /path/:param HeaderParams []ParameterDefinition // Parameters in HTTP headers QueryParams []ParameterDefinition // Parameters in the query, /path?param @@ -436,12 +437,18 @@ func OperationDefinitions(swagger *openapi3.T) ([]OperationDefinition, error) { return nil, fmt.Errorf("error generating body definitions: %w", err) } + var customImports []string + for _, allParam := range allParams { + customImports = append(customImports, allParam.Schema.CustomImports...) + } + opDef := OperationDefinition{ - PathParams: pathParams, - HeaderParams: FilterParameterDefinitionByType(allParams, "header"), - QueryParams: FilterParameterDefinitionByType(allParams, "query"), - CookieParams: FilterParameterDefinitionByType(allParams, "cookie"), - OperationID: ToCamelCase(op.OperationID), + PathParams: pathParams, + CustomImports: customImports, + 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, diff --git a/codegen/schema.go b/codegen/schema.go index 0302a9a6..ac609569 100644 --- a/codegen/schema.go +++ b/codegen/schema.go @@ -10,8 +10,9 @@ import ( // Schema represents an OpenAPI type definition. type Schema struct { - GoType string // The Go type needed to represent the schema - RefType string // If the type has a type name, this is set + CustomImports []string // The custom imports which are needed for x-go-type-external + GoType string // The Go type needed to represent the schema + RefType string // If the type has a type name, this is set ArrayType *Schema // The schema of array element @@ -184,9 +185,10 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { } outSchema := Schema{ - Description: StringToGoComment(schema.Description), - OAPISchema: schema, - Bindable: true, + CustomImports: []string{}, + Description: StringToGoComment(schema.Description), + OAPISchema: schema, + Bindable: true, } // FIXME(hhhapz): We can probably support this in a meaningful way. @@ -208,11 +210,34 @@ func GenerateGoSchema(sref *openapi3.SchemaRef, path []string) (Schema, error) { // Check for custom Go type extension if extension, ok := schema.Extensions[extPropGoType]; ok { - typeName, err := extTypeName(extension) + typeDetails, err := extImportPath(extension) if err != nil { return outSchema, fmt.Errorf("invalid value for %q: %w", extPropGoType, err) } - outSchema.GoType = typeName + + outSchema.GoType = typeDetails.Type + // if we have a custom import for our type as it is an external type we need to the imports + if typeDetails.Import != "" { + // if the import should have an alias it needs to be specified + if typeDetails.Alias != "" { + // we need to set the gotype with the correct import name + outSchema.GoType = fmt.Sprintf("%s.%s", typeDetails.Alias, typeDetails.Type) + outSchema.CustomImports = append(outSchema.CustomImports, fmt.Sprintf("%s \"%s\"", typeDetails.Alias, typeDetails.Import)) + } else { + // as no alias is provided we need to take the import + + // if there is an import name specified instead of an alias, take it + if strings.Contains(typeDetails.Import, ":") { + splitImport := strings.Split(typeDetails.Import, ":") + outSchema.GoType = fmt.Sprintf("%s.%s", splitImport[1], typeDetails.Type) + typeDetails.Import = splitImport[0] + } else { + splitImport := strings.Split(typeDetails.Import, "/") + outSchema.GoType = fmt.Sprintf("%s.%s", splitImport[len(splitImport)-1], typeDetails.Type) + } + outSchema.CustomImports = append(outSchema.CustomImports, fmt.Sprintf("\"%s\"", typeDetails.Import)) + } + } return outSchema, nil } diff --git a/examples/petstore-expanded/api/petstore.go b/examples/petstore-expanded/api/petstore.go index 28cf4271..fb6c2810 100644 --- a/examples/petstore-expanded/api/petstore.go +++ b/examples/petstore-expanded/api/petstore.go @@ -108,7 +108,7 @@ func (p *PetStore) DeletePet(w http.ResponseWriter, r *http.Request, id int64) * if !found { return DeletePetJSONDefaultResponse(Error{fmt.Sprintf(petNotFoundMsg, id)}).Status(http.StatusNotFound) } - delete(p.Pets, id) + delete(p.Pets, int64(id)) return &Response{Code: http.StatusNoContent} } diff --git a/internal/test/schemas/schemas.gen.go b/internal/test/schemas/schemas.gen.go index 35b323ec..3c4c8463 100644 --- a/internal/test/schemas/schemas.gen.go +++ b/internal/test/schemas/schemas.gen.go @@ -16,6 +16,8 @@ import ( "path" "strings" + customAlias "github.com/discord-gophers/goapi-gen/internal/test/schemas/types/alias" + "github.com/discord-gophers/goapi-gen/internal/test/schemas/types/normal" "github.com/discord-gophers/goapi-gen/runtime" "github.com/getkin/kin-openapi/openapi3" "github.com/go-chi/chi/v5" @@ -46,6 +48,12 @@ type AnyType1 interface{} // This should be an interface{} type AnyType2 interface{} +// CustomGoType defines model for CustomGoType. +type CustomGoType normal.CustomGoType + +// CustomGoTypeWithAlias defines model for CustomGoTypeWithAlias. +type CustomGoTypeWithAlias customAlias.CustomGoType + // CustomStringType defines model for CustomStringType. type CustomStringType string @@ -112,6 +120,16 @@ type Issue9Params struct { Foo string `json:"foo"` } +// GetPr66Params defines parameters for GetPr66. +type GetPr66Params struct { + Foo normal.CustomGoType `json:"foo"` +} + +// PostPr66Params defines parameters for PostPr66. +type PostPr66Params struct { + Bar normal.CustomGoType `json:"bar"` +} + // Issue185JSONRequestBody defines body for Issue185 for application/json ContentType. type Issue185JSONRequestBody Issue185JSONBody @@ -232,6 +250,26 @@ func GetIssues375JSON200Response(body EnumInObjInArray) *Response { } } +// GetPr66JSON200Response is a constructor method for a GetPr66 response. +// A *Response is returned with the configured status code and content type from the spec. +func GetPr66JSON200Response(body CustomGoType) *Response { + return &Response{ + body: body, + Code: 200, + contentType: "application/json", + } +} + +// PostPr66JSON200Response is a constructor method for a PostPr66 response. +// A *Response is returned with the configured status code and content type from the spec. +func PostPr66JSON200Response(body CustomGoTypeWithAlias) *Response { + return &Response{ + body: body, + Code: 200, + contentType: "application/json", + } +} + // ServerInterface represents all server handlers. type ServerInterface interface { @@ -258,6 +296,12 @@ type ServerInterface interface { // (GET /issues/9) Issue9(w http.ResponseWriter, r *http.Request, params Issue9Params) *Response + + // (GET /pr/66) + GetPr66(w http.ResponseWriter, r *http.Request, params GetPr66Params) *Response + + // (POST /pr/66) + PostPr66(w http.ResponseWriter, r *http.Request, params PostPr66Params) *Response } // ServerInterfaceWrapper converts contexts to parameters. @@ -430,6 +474,60 @@ func (siw *ServerInterfaceWrapper) Issue9(w http.ResponseWriter, r *http.Request handler(w, r.WithContext(ctx)) } +// GetPr66 operation middleware +func (siw *ServerInterfaceWrapper) GetPr66(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + ctx = context.WithValue(ctx, AccessTokenScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params GetPr66Params + + // ------------- Required query parameter "foo" ------------- + + if err := runtime.BindQueryParameter("form", true, true, "foo", r.URL.Query(), ¶ms.Foo); err != nil { + err = fmt.Errorf("invalid format for parameter foo: %w", err) + siw.ErrorHandlerFunc(w, r, &RequiredParamError{err, "foo"}) + return + } + + var handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + resp := siw.Handler.GetPr66(w, r, params) + if resp != nil { + render.Render(w, r, resp) + } + }) + + handler(w, r.WithContext(ctx)) +} + +// PostPr66 operation middleware +func (siw *ServerInterfaceWrapper) PostPr66(w http.ResponseWriter, r *http.Request) { + ctx := r.Context() + + ctx = context.WithValue(ctx, AccessTokenScopes, []string{""}) + + // Parameter object where we will unmarshal all parameters from the context + var params PostPr66Params + + // ------------- Required query parameter "bar" ------------- + + if err := runtime.BindQueryParameter("form", true, true, "bar", r.URL.Query(), ¶ms.Bar); err != nil { + err = fmt.Errorf("invalid format for parameter bar: %w", err) + siw.ErrorHandlerFunc(w, r, &RequiredParamError{err, "bar"}) + return + } + + var handler = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + resp := siw.Handler.PostPr66(w, r, params) + if resp != nil { + render.Render(w, r, resp) + } + }) + + handler(w, r.WithContext(ctx)) +} + type UnescapedCookieParamError struct { err error paramName string @@ -556,6 +654,8 @@ func Handler(si ServerInterface, opts ...ServerOption) http.Handler { r.Get("/issues/375", wrapper.GetIssues375) r.Get("/issues/41/{1param}", wrapper.Issue41) r.Get("/issues/9", wrapper.Issue9) + r.Get("/pr/66", wrapper.GetPr66) + r.Post("/pr/66", wrapper.PostPr66) }) return r @@ -594,27 +694,30 @@ func WithErrorHandler(handler func(w http.ResponseWriter, r *http.Request, err e // Base64 encoded, gzipped, json marshaled Swagger object var swaggerSpec = []string{ - "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", + "AAA=", } // GetSwagger returns the content of the embedded swagger specification file diff --git a/internal/test/schemas/schemas.yaml b/internal/test/schemas/schemas.yaml index a39db56a..9ead2f8c 100644 --- a/internal/test/schemas/schemas.yaml +++ b/internal/test/schemas/schemas.yaml @@ -121,6 +121,43 @@ paths: application/json: schema: $ref: "#/components/schemas/EnumInObjInArray" + /pr/66: + get: + description: | + This is a test for pull request #66. + parameters: + - name: foo + in: query + required: true + schema: + type: string + x-go-type: + type: CustomGoType + import: github.com/discord-gophers/goapi-gen/internal/test/schemas/types/normal + responses: + 200: + content: + application/json: + schema: + $ref: "#/components/schemas/CustomGoType" + post: + description: | + This is a test for pull request #66. + parameters: + - name: bar + in: query + required: true + schema: + type: string + x-go-type: + type: CustomGoType + import: github.com/discord-gophers/goapi-gen/internal/test/schemas/types/normal + responses: + 200: + content: + application/json: + schema: + $ref: "#/components/schemas/CustomGoTypeWithAlias" components: schemas: GenericObject: @@ -165,6 +202,17 @@ components: enum: - first - second + CustomGoType: + type: string + x-go-type: + type: CustomGoType + import: github.com/discord-gophers/goapi-gen/internal/test/schemas/types/normal + CustomGoTypeWithAlias: + type: string + x-go-type: + type: CustomGoType + import: github.com/discord-gophers/goapi-gen/internal/test/schemas/types/alias + alias: customAlias parameters: StringInPath: name: str diff --git a/internal/test/schemas/schemas_test.go b/internal/test/schemas/schemas_test.go new file mode 100644 index 00000000..b3324518 --- /dev/null +++ b/internal/test/schemas/schemas_test.go @@ -0,0 +1,12 @@ +package schemas + +import ( + "testing" +) + +func TestForCorrectCustomTypes(t *testing.T) { + + _ = CustomGoTypeWithAlias("example") + _ = CustomGoType("example") + +} diff --git a/internal/test/schemas/types/alias/types.go b/internal/test/schemas/types/alias/types.go new file mode 100644 index 00000000..ab71260f --- /dev/null +++ b/internal/test/schemas/types/alias/types.go @@ -0,0 +1,3 @@ +package alias + +type CustomGoType string diff --git a/internal/test/schemas/types/normal/types.go b/internal/test/schemas/types/normal/types.go new file mode 100644 index 00000000..bbcec1b5 --- /dev/null +++ b/internal/test/schemas/types/normal/types.go @@ -0,0 +1,3 @@ +package normal + +type CustomGoType string