205 lines
5.0 KiB
Go
Raw Normal View History

2021-01-01 20:30:52 +08:00
package generate
import (
"fmt"
"github.com/tal-tech/go-zero/tools/goctl/api/spec"
"net/http"
"reflect"
"strconv"
"strings"
)
func applyGenerate(p Plugin) (*swaggerObject, error) {
s := swaggerObject{
Swagger: "2.0",
Schemes: []string{"http", "https"},
Consumes: []string{"application/json"},
Produces: []string{"application/json"},
Paths: make(swaggerPathsObject),
Definitions: make(swaggerDefinitionsObject),
StreamDefinitions: make(swaggerDefinitionsObject),
Info: swaggerInfoObject{
Title: p.Api.Info.Title,
Version: p.Api.Info.Version,
},
}
requestResponseRefs := refMap{}
renderServiceRoutes(p.Api.Service, p.Api.Service.Groups, s.Paths, requestResponseRefs)
m := messageMap{}
renderReplyAsDefinition(s.Definitions, m, p.Api.Types, requestResponseRefs)
return &s, nil
}
func renderServiceRoutes(service spec.Service, groups []spec.Group, paths swaggerPathsObject, requestResponseRefs refMap) {
for _, group := range groups {
for _, route := range group.Routes {
path := route.Path
if strings.Contains(path, "/:") {
}
parameters := swaggerParametersObject{}
reqRef := fmt.Sprintf("#/definitions/%s", route.RequestType.Name)
2021-01-03 16:10:42 +08:00
if len(route.RequestType.Name) > 0 {
var schema = swaggerSchemaObject{
schemaCore: schemaCore{
Ref: reqRef,
},
}
parameters = append(parameters, swaggerParameterObject{
Name: "body",
In: "body",
Required: true,
Schema: &schema,
})
2021-01-01 20:30:52 +08:00
}
pathItemObject, ok := paths[path]
if !ok {
pathItemObject = swaggerPathItemObject{}
}
desc := "A successful response."
respRef := fmt.Sprintf("#/definitions/%s", route.ResponseType.Name)
if len(route.ResponseType.Name) < 1 {
respRef = ""
}
tags := service.Name
if group.Annotations != nil && len(group.Annotations) > 0 {
if groupName, ok := group.Annotations[0].Properties["group"]; ok {
tags = groupName
}
}
operationObject := &swaggerOperationObject{
Tags: []string{tags},
Parameters: parameters,
Responses: swaggerResponsesObject{
"200": swaggerResponseObject{
Description: desc,
Schema: swaggerSchemaObject{
schemaCore: schemaCore{
Ref: respRef,
},
},
},
},
}
operationObject.OperationID = fmt.Sprintf("%s", route.Path)
for _, param := range operationObject.Parameters {
if param.Schema != nil && param.Schema.Ref != "" {
requestResponseRefs[param.Schema.Ref] = struct{}{}
}
}
if len(route.Annotations) > 0 {
operationObject.Summary, _ = strconv.Unquote(route.Annotations[0].Properties["summary"])
operationObject.Description, _ = strconv.Unquote(route.Annotations[0].Properties["description"])
}
switch strings.ToUpper(route.Method) {
case http.MethodGet:
pathItemObject.Get = operationObject
case http.MethodPost:
pathItemObject.Post = operationObject
case http.MethodDelete:
pathItemObject.Delete = operationObject
case http.MethodPut:
pathItemObject.Put = operationObject
}
paths[path] = pathItemObject
}
}
}
func renderReplyAsDefinition(d swaggerDefinitionsObject, m messageMap, p []spec.Type, refs refMap) {
for _, i2 := range p {
schema := swaggerSchemaObject{
schemaCore: schemaCore{
Type: "object",
},
}
schema.Title = i2.Name
for _, member := range i2.Members {
kv := keyVal{Value: schemaOfField(member)}
kv.Key = member.Name
if schema.Properties == nil {
schema.Properties = &swaggerSchemaObjectProperties{}
}
*schema.Properties = append(*schema.Properties, kv)
}
d[i2.Name] = schema
}
}
func schemaOfField(member spec.Member) swaggerSchemaObject {
ret := swaggerSchemaObject{}
var core schemaCore
kind := swaggerMapTypes[member.Type]
var props *swaggerSchemaObjectProperties
switch ft := kind; ft {
case reflect.Invalid:
// []Struct
refTypeName := strings.Replace(member.Type, "[", "", 1)
refTypeName = strings.Replace(refTypeName, "]", "", 1)
core = schemaCore{
Ref: "#/definitions/" + refTypeName,
}
default:
ftype, format, ok := primitiveSchema(ft, member.Type)
if ok {
core = schemaCore{Type: ftype, Format: format}
} else {
core = schemaCore{Type: ft.String(), Format: "UNKNOWN"}
}
}
switch ft := kind; ft {
case reflect.Slice, reflect.Invalid:
ret = swaggerSchemaObject{
schemaCore: schemaCore{
Type: "array",
Items: (*swaggerItemsObject)(&core),
},
}
default:
ret = swaggerSchemaObject{
schemaCore: core,
Properties: props,
}
}
return ret
}
2021-01-03 16:10:42 +08:00
// https://swagger.io/specification/ Data Types
2021-01-01 20:30:52 +08:00
func primitiveSchema(kind reflect.Kind, t string) (ftype, format string, ok bool) {
switch kind {
case reflect.Int:
return "integer", "int32", true
2021-01-03 16:10:42 +08:00
case reflect.Int64:
return "integer", "int64", true
2021-01-01 20:30:52 +08:00
case reflect.Bool:
return "boolean", "boolean", true
case reflect.String:
return "string", "", true
case reflect.Slice:
return strings.Replace(t, "[]", "", -1), "", true
default:
return "", "", false
}
}