diff --git a/examples/bare/README.md b/examples/bare/README.md new file mode 100644 index 0000000..54a8377 --- /dev/null +++ b/examples/bare/README.md @@ -0,0 +1,12 @@ + +Examples of gooo api. + + +## How to run + +## Generate code from swagger.yml + +```bash +go run cmd/app.go +``` + diff --git a/examples/bare/cmd/app.go b/examples/bare/cmd/app.go index 923f3cd..e2d7fe8 100644 --- a/examples/bare/cmd/app.go +++ b/examples/bare/cmd/app.go @@ -6,12 +6,12 @@ import ( "net/http" "time" + "github.com/gooolib/logger" "github.com/version-1/gooo/examples/bare/internal/swagger" "github.com/version-1/gooo/pkg/core/api/app" "github.com/version-1/gooo/pkg/core/api/request" "github.com/version-1/gooo/pkg/core/api/response" "github.com/version-1/gooo/pkg/core/api/route" - "github.com/gooolib/logger" "github.com/version-1/gooo/pkg/toolkit/middleware" ) diff --git a/examples/core/README.md b/examples/core/README.md new file mode 100644 index 0000000..da6e44d --- /dev/null +++ b/examples/core/README.md @@ -0,0 +1,18 @@ + +Examples of gooo to generate code from a swagger.yml file. + + +## How to run + +## Generate code from swagger.yml + +```bash +go run cmd/app.go +``` + +## Run Server + +```bash + +go run generated/cmd/main.go +``` diff --git a/examples/core/generated/cmd/main.go b/examples/core/generated/cmd/main.go new file mode 100644 index 0000000..1830832 --- /dev/null +++ b/examples/core/generated/cmd/main.go @@ -0,0 +1,35 @@ +package main + +// This is a generated file. DO NOT EDIT manually. +import ( + "context" + "log" + "net/http" + + "github.com/gooolib/logger" + "github.com/version-1/gooo/examples/core/generated/internal/routes" + "github.com/version-1/gooo/pkg/core/api/app" +) + +func main() { + cfg := &app.Config{} + cfg.SetLogger(logger.DefaultLogger) + + server := &app.App{ + Addr: ":8080", + Config: cfg, + ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { + cfg.Logger().Errorf("Error: %+v", err) + w.WriteHeader(http.StatusInternalServerError) + w.Write([]byte("Internal server error")) + }, + } + + routeList := routes.Routes() + app.WithDefaultMiddlewares(server, routeList...) + + ctx := context.Background() + if err := server.Run(ctx); err != nil { + log.Fatalf("failed to run app: %s", err) + } +} diff --git a/examples/core/generated/internal/routes/routeimplments.go b/examples/core/generated/internal/routes/routeimplments.go new file mode 100644 index 0000000..1e9197f --- /dev/null +++ b/examples/core/generated/internal/routes/routeimplments.go @@ -0,0 +1,47 @@ +package routes + +import ( + "github.com/version-1/gooo/examples/core/generated/internal/schema" + "github.com/version-1/gooo/pkg/core/api/request" + "github.com/version-1/gooo/pkg/core/api/response" +) + +func GetUsers(res *response.Response[schema.User], req *request.Request[request.Void]) { + // do something +} + +func PostUsers(res *response.Response[schema.User], req *request.Request[schema.MutateUser]) { + // do something +} + +func PatchUsersId(res *response.Response[schema.User], req *request.Request[schema.MutateUser]) { + // do something +} + +func DeleteUsersId(res *response.Response[schema.User], req *request.Request[request.Void]) { + // do something +} + +func GetUsersId(res *response.Response[schema.User], req *request.Request[request.Void]) { + // do something +} + +func GetPosts(res *response.Response[schema.Post], req *request.Request[request.Void]) { + // do something +} + +func PostPosts(res *response.Response[schema.Post], req *request.Request[schema.MutatePost]) { + // do something +} + +func PatchPostsId(res *response.Response[schema.Post], req *request.Request[schema.MutatePost]) { + // do something +} + +func DeletePostsId(res *response.Response[schema.Post], req *request.Request[request.Void]) { + // do something +} + +func GetPostsId(res *response.Response[schema.Post], req *request.Request[request.Void]) { + // do something +} diff --git a/examples/core/generated/internal/routes/routes.go b/examples/core/generated/internal/routes/routes.go new file mode 100644 index 0000000..d4fb8b6 --- /dev/null +++ b/examples/core/generated/internal/routes/routes.go @@ -0,0 +1,90 @@ +package routes + +// This is a generated file. DO NOT EDIT manually. +import ( + "github.com/version-1/gooo/examples/core/generated/internal/schema" + "github.com/version-1/gooo/pkg/core/api/request" + "github.com/version-1/gooo/pkg/core/api/response" + "github.com/version-1/gooo/pkg/core/api/route" +) + +func PostUsersHandler() route.HandlerInterface { + return route.JSON[schema.MutateUser, schema.User]().Get("/users", func(res *response.Response[schema.User], req *request.Request[schema.MutateUser]) { + PostUsers(res, req) + }) +} + +func GetUsersHandler() route.HandlerInterface { + return route.JSON[request.Void, schema.User]().Get("/users", func(res *response.Response[schema.User], req *request.Request[request.Void]) { + GetUsers(res, req) + }) +} + +func GetUsersIdHandler() route.HandlerInterface { + return route.JSON[request.Void, schema.User]().Get("/users/{id}", func(res *response.Response[schema.User], req *request.Request[request.Void]) { + GetUsersId(res, req) + }) +} + +func PatchUsersIdHandler() route.HandlerInterface { + return route.JSON[schema.MutateUser, schema.User]().Get("/users/{id}", func(res *response.Response[schema.User], req *request.Request[schema.MutateUser]) { + PatchUsersId(res, req) + }) +} + +func DeleteUsersIdHandler() route.HandlerInterface { + return route.JSON[request.Void, schema.User]().Get("/users/{id}", func(res *response.Response[schema.User], req *request.Request[request.Void]) { + DeleteUsersId(res, req) + }) +} + +func GetPostsHandler() route.HandlerInterface { + return route.JSON[request.Void, schema.Post]().Get("/posts", func(res *response.Response[schema.Post], req *request.Request[request.Void]) { + GetPosts(res, req) + }) +} + +func PostPostsHandler() route.HandlerInterface { + return route.JSON[schema.MutatePost, schema.Post]().Get("/posts", func(res *response.Response[schema.Post], req *request.Request[schema.MutatePost]) { + PostPosts(res, req) + }) +} + +func GetPostsIdHandler() route.HandlerInterface { + return route.JSON[request.Void, schema.Post]().Get("/posts/{id}", func(res *response.Response[schema.Post], req *request.Request[request.Void]) { + GetPostsId(res, req) + }) +} + +func PatchPostsIdHandler() route.HandlerInterface { + return route.JSON[schema.MutatePost, schema.Post]().Get("/posts/{id}", func(res *response.Response[schema.Post], req *request.Request[schema.MutatePost]) { + PatchPostsId(res, req) + }) +} + +func DeletePostsIdHandler() route.HandlerInterface { + return route.JSON[request.Void, schema.Post]().Get("/posts/{id}", func(res *response.Response[schema.Post], req *request.Request[request.Void]) { + DeletePostsId(res, req) + }) +} + +func Routes() []route.HandlerInterface { + routes := route.GroupHandler{ + Path: "/users", + + Handlers: []route.HandlerInterface{ + PostUsersHandler(), + GetUsersHandler(), + GetUsersIdHandler(), + PatchUsersIdHandler(), + DeleteUsersIdHandler(), + GetPostsHandler(), + PostPostsHandler(), + GetPostsIdHandler(), + PatchPostsIdHandler(), + DeletePostsIdHandler(), + }, + } + + return routes.Children() +} diff --git a/examples/core/generated/main.go b/examples/core/generated/main.go deleted file mode 100644 index 44880e6..0000000 --- a/examples/core/generated/main.go +++ /dev/null @@ -1,75 +0,0 @@ -package main - -// This is a generated file. DO NOT EDIT manually. -import ( - "context" - "log" - "net/http" - - "github.com/version-1/gooo/examples/core/generated/internal/schema" - "github.com/version-1/gooo/pkg/core/api/app" - "github.com/version-1/gooo/pkg/core/api/request" - "github.com/version-1/gooo/pkg/core/api/response" - "github.com/version-1/gooo/pkg/core/api/route" - "github.com/gooolib/logger" -) - -func main() { - cfg := &app.Config{} - cfg.SetLogger(logger.DefaultLogger) - - server := &app.App{ - Addr: ":8080", - Config: cfg, - ErrorHandler: func(w http.ResponseWriter, r *http.Request, err error) { - cfg.Logger().Errorf("Error: %+v", err) - w.WriteHeader(http.StatusInternalServerError) - w.Write([]byte("Internal server error")) - }, - } - - RegisterRoutes(server) - ctx := context.Background() - if err := server.Run(ctx); err != nil { - log.Fatalf("failed to run app: %s", err) - } -} - -func RegisterRoutes(srv *app.App) { - routes := route.GroupHandler{ - Path: "/users", - Handlers: []route.HandlerInterface{ - route.JSON[schema.MutateUser, schema.User]().Post("/users", func(res *response.Response[schema.User], req *request.Request[schema.MutateUser]) { - // do something - }), - route.JSON[request.Void, schema.User]().Get("/users", func(res *response.Response[schema.User], req *request.Request[request.Void]) { - // do something - }), - route.JSON[request.Void, schema.User]().Get("/users/{id}", func(res *response.Response[schema.User], req *request.Request[request.Void]) { - // do something - }), - route.JSON[schema.MutateUser, schema.User]().Patch("/users/{id}", func(res *response.Response[schema.User], req *request.Request[schema.MutateUser]) { - // do something - }), - route.JSON[request.Void, schema.User]().Delete("/users/{id}", func(res *response.Response[schema.User], req *request.Request[request.Void]) { - // do something - }), - route.JSON[request.Void, schema.Post]().Get("/posts", func(res *response.Response[schema.Post], req *request.Request[request.Void]) { - // do something - }), - route.JSON[schema.MutatePost, schema.Post]().Post("/posts", func(res *response.Response[schema.Post], req *request.Request[schema.MutatePost]) { - // do something - }), - route.JSON[schema.MutatePost, schema.Post]().Patch("/posts/{id}", func(res *response.Response[schema.Post], req *request.Request[schema.MutatePost]) { - // do something - }), - route.JSON[request.Void, schema.Post]().Delete("/posts/{id}", func(res *response.Response[schema.Post], req *request.Request[request.Void]) { - // do something - }), - route.JSON[request.Void, schema.Post]().Get("/posts/{id}", func(res *response.Response[schema.Post], req *request.Request[request.Void]) { - // do something - }), - }, - } - app.WithDefaultMiddlewares(srv, routes.Children()...) -} diff --git a/pkg/core/schema/generate.go b/pkg/core/schema/generate.go index 811f2d4..5f6066e 100644 --- a/pkg/core/schema/generate.go +++ b/pkg/core/schema/generate.go @@ -22,11 +22,24 @@ func NewGenerator(r *v3_0_0.RootSchema, outDir string, baseURL string) *Generato func (g *Generator) Generate() error { schemaFile := template.SchemaFile{Schema: g.r, PackageName: "schema"} + routeImplementsFile := template.RouteImplementsFile{Schema: g.r, PackageName: "routes"} + routeImplementsFile.Dependencies = []string{ + fmt.Sprintf("%s/%s", g.baseURL, filepath.Dir(schemaFile.Filename())), + } + routesFile := template.RoutesFile{Schema: g.r, PackageName: "routes"} + routesFile.Dependencies = []string{ + fmt.Sprintf("%s/%s", g.baseURL, filepath.Dir(schemaFile.Filename())), + } + mainFile := template.Main{Schema: g.r} - mainFile.Dependencies = []string{fmt.Sprintf("%s/%s", g.baseURL, filepath.Dir(schemaFile.Filename()))} + mainFile.Dependencies = []string{ + fmt.Sprintf("%s/%s", g.baseURL, filepath.Dir(routesFile.Filename())), + } g.outputs = append(g.outputs, schemaFile) + g.outputs = append(g.outputs, routeImplementsFile) + g.outputs = append(g.outputs, routesFile) g.outputs = append(g.outputs, mainFile) for _, tmpl := range g.outputs { diff --git a/pkg/core/schema/template/common.go b/pkg/core/schema/template/common.go new file mode 100644 index 0000000..84d379b --- /dev/null +++ b/pkg/core/schema/template/common.go @@ -0,0 +1,29 @@ +package template + +import ( + "bytes" + "embed" + "text/template" + + "github.com/gooolib/errors" +) + +//go:embed components/common/*.go.tmpl +var commonTmpl embed.FS + +type CommonPlainTemplateParams struct { + Package string + HeadComments string + Dependencies []string + Content string +} + +func (p CommonPlainTemplateParams) Render() (string, error) { + var b bytes.Buffer + tmpl := template.Must(template.New("plain").ParseFS(commonTmpl, "components/common/plain.go.tmpl")) + if err := tmpl.ExecuteTemplate(&b, "plain.go.tmpl", p); err != nil { + return "", errors.Wrap(err) + } + + return b.String(), nil +} diff --git a/pkg/core/schema/template/components/common/plain.go.tmpl b/pkg/core/schema/template/components/common/plain.go.tmpl new file mode 100644 index 0000000..ef47642 --- /dev/null +++ b/pkg/core/schema/template/components/common/plain.go.tmpl @@ -0,0 +1,10 @@ +package {{ .Package }} + +{{ .HeadComments }} +import ( + {{ range .Dependencies }} + "{{ . }}" + {{ end }} +) + +{{ .Content }} diff --git a/pkg/core/schema/template/components/entry.go.tmpl b/pkg/core/schema/template/components/entry.go.tmpl index 6697103..4a6c74b 100644 --- a/pkg/core/schema/template/components/entry.go.tmpl +++ b/pkg/core/schema/template/components/entry.go.tmpl @@ -21,19 +21,12 @@ func main() { }, } - RegisterRoutes(server) + routeList := routes.Routes() + app.WithDefaultMiddlewares(server, routeList...) + ctx := context.Background() if err := server.Run(ctx); err != nil { log.Fatalf("failed to run app: %s", err) } } -func RegisterRoutes(srv *app.App) { - routes := route.GroupHandler{ - Path: "/users", - Handlers: []route.HandlerInterface{ - {{ .Routes }} - }, - } - app.WithDefaultMiddlewares(srv, routes.Children()...) -} diff --git a/pkg/core/schema/template/components/route.go.tmpl b/pkg/core/schema/template/components/route.go.tmpl deleted file mode 100644 index 5495507..0000000 --- a/pkg/core/schema/template/components/route.go.tmpl +++ /dev/null @@ -1,3 +0,0 @@ -route.JSON[{{.InputType}}, {{.OutputType}}]().{{.Method}}("{{.Path}}", func(res *response.Response[{{.OutputType}}], req *request.Request[{{.InputType}}]) { - // do something -}), diff --git a/pkg/core/schema/template/components/routehandler.go.tmpl b/pkg/core/schema/template/components/routehandler.go.tmpl new file mode 100644 index 0000000..33c8477 --- /dev/null +++ b/pkg/core/schema/template/components/routehandler.go.tmpl @@ -0,0 +1,6 @@ +func {{ .FuncName }}Handler() route.HandlerInterface { + return route.JSON[{{.InputType}}, {{.OutputType}}]().Get("{{.Path}}", func(res *response.Response[{{ .OutputType }}], req *request.Request[{{ .InputType }}]) { + {{ .FuncName }}(res, req) + }) +} + diff --git a/pkg/core/schema/template/components/routeimpl.go.tmpl b/pkg/core/schema/template/components/routeimpl.go.tmpl new file mode 100644 index 0000000..a3ca4c9 --- /dev/null +++ b/pkg/core/schema/template/components/routeimpl.go.tmpl @@ -0,0 +1,4 @@ +func {{ .FuncName }}(res *response.Response[{{.OutputType}}], req *request.Request[{{.InputType}}]) { + // do something +} + diff --git a/pkg/core/schema/template/components/routes.go.tmpl b/pkg/core/schema/template/components/routes.go.tmpl new file mode 100644 index 0000000..ffab122 --- /dev/null +++ b/pkg/core/schema/template/components/routes.go.tmpl @@ -0,0 +1,22 @@ +package routes + +// This is a generated file. DO NOT EDIT manually. +import ( + {{ range .Dependencies }} + "{{ . }}" + {{ end }} +) + +{{ .RouteHandlers }} + +func Routes() []route.HandlerInterface { + routes := route.GroupHandler{ + Path: "/users", + + Handlers: []route.HandlerInterface{ + {{ .Routes }} + }, + } + + return routes.Children() +} diff --git a/pkg/core/schema/template/main.go b/pkg/core/schema/template/main.go index 5301877..a559bb7 100644 --- a/pkg/core/schema/template/main.go +++ b/pkg/core/schema/template/main.go @@ -5,8 +5,8 @@ import ( "embed" "text/template" - "github.com/version-1/gooo/pkg/core/schema/openapi/v3_0_0" "github.com/gooolib/errors" + "github.com/version-1/gooo/pkg/core/schema/openapi/v3_0_0" ) //go:embed components/*.go.tmpl @@ -15,21 +15,13 @@ var tmpl embed.FS type Main struct { Schema *v3_0_0.RootSchema Dependencies []string - Routes string } func (m Main) Filename() string { - return "main" + return "cmd/main" } func (m Main) Render() (string, error) { - routes, err := renderRoutes(extractRoutes(m.Schema)) - if err != nil { - return "", err - } - - m.Routes = routes - tmpl := template.Must(template.New("entry").ParseFS(tmpl, "components/entry.go.tmpl")) var b bytes.Buffer if err := tmpl.ExecuteTemplate(&b, "entry.go.tmpl", m); err != nil { diff --git a/pkg/core/schema/template/route.go b/pkg/core/schema/template/route.go index 8e48173..ac4883f 100644 --- a/pkg/core/schema/template/route.go +++ b/pkg/core/schema/template/route.go @@ -2,33 +2,157 @@ package template import ( "bytes" - "strconv" - "strings" + "fmt" "text/template" - "github.com/version-1/gooo/pkg/core/schema/openapi/v3_0_0" - "github.com/version-1/gooo/pkg/core/schema/openapi/yaml" "github.com/gooolib/errors" + "github.com/version-1/gooo/pkg/core/schema/openapi/v3_0_0" + "github.com/version-1/gooo/pkg/core/schema/template/route" ) +type RouteImplementsFile struct { + Schema *v3_0_0.RootSchema + PackageName string + Dependencies []string +} + +func (r RouteImplementsFile) Filename() string { + return "internal/routes/routeimplments" +} + +type RouteImplementsTemplateParams struct { + Functions string +} + +func (r RouteImplementsFile) Render() (string, error) { + routes := extractRoutes(r.Schema) + implString, err := renderRouteImplements(routes) + if err != nil { + return "", err + } + + p := CommonPlainTemplateParams{ + Package: r.PackageName, + Dependencies: r.Dependencies, + Content: implString, + } + + content, err := p.Render() + + res, err := pretify(r.Filename(), content) + if err != nil { + return "", errors.Wrap(err) + } + + return string(res), nil +} + +type RoutesFile struct { + Schema *v3_0_0.RootSchema + PackageName string + Dependencies []string +} + +type RoutesTemplateParams struct { + Routes string + RouteHandlers string + RouteImplements string + Dependencies []string +} + +func (r RoutesFile) Filename() string { + return "internal/routes/routes" +} + +func (r RoutesFile) Render() (string, error) { + routes := extractRoutes(r.Schema) + handlersString, err := renderRouteHandlers(routes) + routeString := renderRoutes(routes) + + p := RoutesTemplateParams{ + Routes: routeString, + RouteHandlers: handlersString, + Dependencies: r.Dependencies, + } + + var b bytes.Buffer + tmpl := template.Must(template.New("routes").ParseFS(tmpl, "components/routes.go.tmpl")) + if err := tmpl.ExecuteTemplate(&b, "routes.go.tmpl", p); err != nil { + return "", errors.Wrap(err) + } + + res, err := pretify(r.Filename(), b.String()) + if err != nil { + return "", errors.Wrap(err) + } + + return string(res), nil +} + type Route struct { + Name string InputType string OutputType string Method string Path string } -func renderRoutes(routes []Route) (string, error) { +func renderRouteHandlers(routes []Route) (string, error) { + var b bytes.Buffer + for _, r := range routes { + tmpl := template.Must(template.New("route").ParseFS(tmpl, "components/routehandler.go.tmpl")) + p := struct { + FuncName string + Path string + InputType string + OutputType string + }{ + FuncName: r.Name, + Path: r.Path, + InputType: r.InputType, + OutputType: r.OutputType, + } + + if err := tmpl.ExecuteTemplate(&b, "routehandler.go.tmpl", p); err != nil { + return "", errors.Wrap(err) + } + } + + return b.String(), nil +} + +func renderRouteImplements(routes []Route) (string, error) { var b bytes.Buffer for _, r := range routes { - tmpl := template.Must(template.New("route").ParseFS(tmpl, "components/route.go.tmpl")) - if err := tmpl.ExecuteTemplate(&b, "route.go.tmpl", r); err != nil { + tmpl := template.Must(template.New("route").ParseFS(tmpl, "components/routeimpl.go.tmpl")) + p := struct { + FuncName string + Path string + InputType string + OutputType string + }{ + FuncName: r.Name, + Path: r.Path, + InputType: r.InputType, + OutputType: r.OutputType, + } + + if err := tmpl.ExecuteTemplate(&b, "routeimpl.go.tmpl", p); err != nil { return "", errors.Wrap(err) } } + return b.String(), nil } +func renderRoutes(routes []Route) string { + var b bytes.Buffer + for _, r := range routes { + b.WriteString(fmt.Sprintf("%sHandler(),\n", r.Name)) + } + return b.String() +} + func extractRoutes(r *v3_0_0.RootSchema) []Route { routes := []Route{} r.Paths.Each(func(path string, pathItem v3_0_0.PathItem) error { @@ -44,10 +168,12 @@ func extractRoutes(r *v3_0_0.RootSchema) []Route { continue } + routeName := route.ResolveRouteName(k, path, v) if k == "Get" || k == "Delete" { route := Route{ + Name: routeName, InputType: "request.Void", - OutputType: withSchemaPackageName(detectOutputType(v, 200, "application/json")), + OutputType: withSchemaPackageName(route.DetectOutputType(v, 200, "application/json")), Method: k, Path: path, } @@ -59,8 +185,9 @@ func extractRoutes(r *v3_0_0.RootSchema) []Route { statusCode = 201 } route := Route{ - InputType: withSchemaPackageName(detectInputType(v, "application/json")), - OutputType: withSchemaPackageName(detectOutputType(v, statusCode, "application/json")), + Name: routeName, + InputType: withSchemaPackageName(route.DetectInputType(v, "application/json")), + OutputType: withSchemaPackageName(route.DetectOutputType(v, statusCode, "application/json")), Method: k, Path: path, } @@ -73,34 +200,3 @@ func extractRoutes(r *v3_0_0.RootSchema) []Route { return routes } - -func detectInputType(op *v3_0_0.Operation, contentType string) string { - schema := op.RequestBody.Content.Get(contentType).Schema - ref := "" - if schema.Ref != "" { - ref = schema.Ref - } - - if schema.Items.Type == "array" && schema.Items.Ref != "" { - ref = schema.Items.Ref - } - - schemaName := strings.Replace(ref, "#/components/schemas/", "", 1) - return schemaName -} - -func detectOutputType(op *v3_0_0.Operation, statusCode int, contentType string) string { - responses := yaml.OrderedMap[v3_0_0.Response](op.Responses) - schema := responses.Get(strconv.Itoa(statusCode)).Content.Get(contentType).Schema - ref := "" - if schema.Ref != "" { - ref = schema.Ref - } - - if schema.Type == "array" && schema.Items.Ref != "" { - ref = schema.Items.Ref - } - - schemaName := strings.Replace(ref, "#/components/schemas/", "", 1) - return schemaName -} diff --git a/pkg/core/schema/template/route/route.go b/pkg/core/schema/template/route/route.go new file mode 100644 index 0000000..45b18c3 --- /dev/null +++ b/pkg/core/schema/template/route/route.go @@ -0,0 +1,58 @@ +package route + +import ( + "strconv" + gostrings "strings" + + "github.com/version-1/gooo/pkg/core/schema/openapi/v3_0_0" + "github.com/version-1/gooo/pkg/core/schema/openapi/yaml" + "github.com/version-1/gooo/pkg/toolkit/strings" +) + +func ResolveRouteName(method, path string, operation *v3_0_0.Operation) string { + if operation.OperationId != "" { + return strings.ToCamelCase(operation.OperationId) + } + + name := strings.ToPascalCase(method) + for _, p := range gostrings.Split(path, "/") { + if gostrings.HasPrefix(p, "{") && gostrings.HasSuffix(p, "}") { + name += strings.ToPascalCase(p[1 : len(p)-1]) + } else { + name += strings.ToPascalCase(p) + } + } + + return name +} + +func DetectInputType(op *v3_0_0.Operation, contentType string) string { + schema := op.RequestBody.Content.Get(contentType).Schema + ref := "" + if schema.Ref != "" { + ref = schema.Ref + } + + if schema.Items.Type == "array" && schema.Items.Ref != "" { + ref = schema.Items.Ref + } + + schemaName := gostrings.Replace(ref, "#/components/schemas/", "", 1) + return schemaName +} + +func DetectOutputType(op *v3_0_0.Operation, statusCode int, contentType string) string { + responses := yaml.OrderedMap[v3_0_0.Response](op.Responses) + schema := responses.Get(strconv.Itoa(statusCode)).Content.Get(contentType).Schema + ref := "" + if schema.Ref != "" { + ref = schema.Ref + } + + if schema.Type == "array" && schema.Items.Ref != "" { + ref = schema.Items.Ref + } + + schemaName := gostrings.Replace(ref, "#/components/schemas/", "", 1) + return schemaName +}