diff --git a/cmd/gen_route.go b/cmd/gen_route.go new file mode 100644 index 0000000..03816fa --- /dev/null +++ b/cmd/gen_route.go @@ -0,0 +1,401 @@ +package cmd + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "io/fs" + "log" + "os" + "path/filepath" + "regexp" + "strings" + + "git.ipao.vip/rogeecn/atomctl/pkg/utils/gomod" + "github.com/iancoleman/strcase" + "github.com/pkg/errors" + "github.com/samber/lo" + "github.com/spf13/cobra" +) + +func CommandGenRoute(root *cobra.Command) { + cmd := &cobra.Command{ + Use: "route", + Short: "generate routes", + RunE: commandGenRouteE, + } + + root.AddCommand(cmd) +} + +func commandGenRouteE(cmd *cobra.Command, args []string) error { + var err error + var path string + if len(args) > 0 { + path = args[0] + } else { + path, err = os.Getwd() + if err != nil { + return err + } + } + + path, _ = filepath.Abs(path) + + err = gomod.Parse(filepath.Join(path, "go.mod")) + if err != nil { + return err + } + + routes := []RouteDefinition{} + + modulePath := filepath.Join(path, "modules") + if _, err := os.Stat(modulePath); os.IsNotExist(err) { + log.Fatal("modules dir not exist, ", modulePath) + } + + filepath.WalkDir(modulePath, func(path string, d fs.DirEntry, err error) error { + if d.IsDir() { + return nil + } + if !strings.HasSuffix(path, "_controller.go") { + return nil + } + if !strings.HasSuffix(path, ".go") { + return nil + } + + routes = append(routes, astParseRoutes(path)...) + return nil + }) + + routeGroups := lo.GroupBy(routes, func(item RouteDefinition) string { + return filepath.Dir(item.Path) + }) + + for key, routes := range routeGroups { + routePath := filepath.Join(key, "routes.gen.go") + + imports := lo.FlatMap(routes, func(item RouteDefinition, index int) []string { + return lo.Map(item.Imports, func(item string, index int) string { + return fmt.Sprintf("\t%s", item) + }) + }) + + pkgName := filepath.Base(key) + + f, err := os.OpenFile(routePath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0o644) + if err != nil { + fmt.Printf("ERR: %s %s\n", err, routePath) + continue + } + defer f.Close() + + _, _ = f.WriteString("// Code generated by the atomctl; DO NOT EDIT.\n\n") + _, _ = f.WriteString("package " + pkgName + "\n\n") + _, _ = f.WriteString("import (\n") + _, _ = f.WriteString(strings.Join(imports, "\n")) + _, _ = f.WriteString("\n") + _, _ = f.WriteString("\n") + + _, _ = f.WriteString("\t\"github.com/atom-providers/log\"\n") + _, _ = f.WriteString("\t\"git.ipao.vip/rogeecn/atom/contracts\"\n") + _, _ = f.WriteString("\t\"github.com/gofiber/fiber/v3\"\n") + _, _ = f.WriteString("\t. \"github.com/pkg/f\"\n") + _, _ = f.WriteString(")\n\n") + + _, _ = f.WriteString("// @provider contracts.HttpRoute atom.GroupRoutes\n") + _, _ = f.WriteString("type Routes struct {\n") + _, _ = f.WriteString("\tengine\t*fiber.App `inject:\"false\"`\n") + _, _ = f.WriteString("\tsvc\tcontracts.HttpService\n") + // inject controllers + for _, route := range routes { + _, _ = f.WriteString(fmt.Sprintf("\t%s *%s", strcase.ToLowerCamel(route.Name), route.Name)) + } + _, _ = f.WriteString("\n}\n\n") + + _, _ = f.WriteString("func (r *Routes) Prepare() error {\n") + _, _ = f.WriteString("\tlog.Infof(\"register route group: " + pkgName + "\")\n") + _, _ = f.WriteString("\tr.engine = r.svc.GetEngine().(*fiber.App)\n") + + for _, route := range routes { + funcName := fmt.Sprintf(`register%sRoutes()`, route.Name) + _, _ = f.WriteString(fmt.Sprintf("\tr.%s\n", funcName)) + } + _, _ = f.WriteString("\treturn nil\n") + _, _ = f.WriteString("}\n\n") + + for _, route := range routes { + funcName := fmt.Sprintf(`func (r *Routes)register%sRoutes()`, route.Name) + _, _ = f.WriteString(fmt.Sprintf(`%s{`, funcName)) + _, _ = f.WriteString("\n") + + for _, action := range route.Actions { + _, _ = f.WriteString("\t") + _, _ = f.WriteString(fmt.Sprintf("r.engine.%s(%q, ", strcase.ToCamel(strings.ToLower(action.Method)), formatRoute(action.Route))) + + if action.HasData { + _, _ = f.WriteString("Data") + } + _, _ = f.WriteString("Func") + + paramsSize := len(action.Params) + if paramsSize >= 1 { + _, _ = f.WriteString(fmt.Sprintf("%d", paramsSize)) + } + + paramsStrings := []string{fmt.Sprintf("r.%s.%s", strcase.ToLowerCamel(route.Name), action.Name)} + for _, p := range action.Params { + var paramString string + switch p.Position { + case PositionPath: + paramString = fmt.Sprintf(`Path[%s](%q)`, p.Type, p.Name) + case PositionURI: + paramString = fmt.Sprintf(`URI[%s]()`, p.Type) + case PositionQuery: + paramString = fmt.Sprintf(`Query[%s]()`, p.Type) + case PositionBody: + paramString = fmt.Sprintf(`Body[%s]()`, p.Type) + case PositionHeader: + paramString = fmt.Sprintf(`Header[%s]()`, p.Type) + case PositionCookie: + paramString = fmt.Sprintf(`Cookie[%s]()`, p.Type) + } + + paramsStrings = append(paramsStrings, paramString) + } + _, _ = f.WriteString("(" + strings.Join(paramsStrings, ", ") + ")") + + _, _ = f.WriteString(")\n") + } + + _, _ = f.WriteString("}\n") + } + } + + return nil +} + +type RouteDefinition struct { + Path string + Name string + Imports []string + Actions []ActionDefinition +} + +type ParamDefinition struct { + Name string + Type string + Position Position +} + +type ActionDefinition struct { + Route string + Method string + Name string + HasData bool + Params []ParamDefinition +} +type Position string + +const ( + PositionPath Position = "Path" + PositionURI Position = "Uri" + PositionQuery Position = "Query" + PositionBody Position = "Body" + PositionHeader Position = "Header" + PositionCookie Position = "Cookie" +) + +func astParseRoutes(source string) []RouteDefinition { + if strings.HasSuffix(source, "_test.go") { + return []RouteDefinition{} + } + + if strings.HasSuffix(source, "/provider.go") { + return []RouteDefinition{} + } + + fset := token.NewFileSet() + node, err := parser.ParseFile(fset, source, nil, parser.ParseComments) + if err != nil { + log.Println("ERR: ", err) + return nil + } + + imports := make(map[string]string) + for _, imp := range node.Imports { + paths := strings.Split(strings.Trim(imp.Path.Value, "\""), "/") + name := paths[len(paths)-1] + pkg := imp.Path.Value + if imp.Name != nil { + name = imp.Name.Name + pkg = fmt.Sprintf("%s %q", name, imp.Path.Value) + } + imports[name] = pkg + } + + routes := make(map[string]RouteDefinition) + actions := make(map[string][]ActionDefinition) + usedImports := make(map[string][]string) + + // 再去遍历 struct 的方法去 + for _, decl := range node.Decls { + decl, ok := decl.(*ast.FuncDecl) + if !ok { + continue + } + + // 普通方法不要 + if decl.Recv == nil { + continue + } + + recvType := decl.Recv.List[0].Type.(*ast.StarExpr).X.(*ast.Ident).Name + if _, ok := routes[recvType]; !ok { + routes[recvType] = RouteDefinition{ + Name: recvType, + Path: source, + Actions: []ActionDefinition{}, + } + actions[recvType] = []ActionDefinition{} + } + + // Doc 中把 @Router 的定义拿出来, Route 格式为 /user/:id [get] 两部分,表示路径和请求方法 + var path, method string + var err error + if decl.Doc != nil { + for _, line := range decl.Doc.List { + lineText := strings.TrimSpace(line.Text) + lineText = strings.TrimLeft(lineText, "/ \t") + if !strings.HasPrefix(lineText, "@Route") { + continue + } + + path, method, err = parseRouteComment(lineText) + if err != nil { + log.Fatal(errors.Wrapf(err, "file: %s, action: %s", source, decl.Name.Name)) + } + break + } + } + if path == "" || method == "" { + log.Printf("[WARN] failed to get router ,file: %s, action: %s", source, decl.Name.Name) + continue + } + + // 拿参数列表去, 忽略 context.Context 参数 + params := []ParamDefinition{} + for _, param := range decl.Type.Params.List { + // paramsType, ok := param.Type.(*ast.SelectorExpr) + + var typ string + switch param.Type.(type) { + case *ast.Ident: + typ = param.Type.(*ast.Ident).Name + case *ast.StarExpr: + paramsType := param.Type.(*ast.StarExpr) + switch paramsType.X.(type) { + case *ast.SelectorExpr: + X := paramsType.X.(*ast.SelectorExpr) + typ = fmt.Sprintf("*%s.%s", X.X.(*ast.Ident).Name, X.Sel.Name) + default: + typ = fmt.Sprintf("*%s", paramsType.X.(*ast.Ident).Name) + } + case *ast.SelectorExpr: + typ = fmt.Sprintf("%s.%s", param.Type.(*ast.SelectorExpr).X.(*ast.Ident).Name, param.Type.(*ast.SelectorExpr).Sel.Name) + } + + if strings.HasSuffix(typ, "Context") || strings.HasSuffix(typ, "Ctx") { + continue + } + pkgName := strings.Split(strings.Trim(typ, "*"), ".") + if len(pkgName) == 2 { + usedImports[recvType] = append(usedImports[recvType], imports[pkgName[0]]) + } + + position := PositionPath + if strings.HasSuffix(typ, string(PositionQuery)) || strings.HasSuffix(typ, "QueryFilter") { + position = PositionQuery + } + if strings.HasSuffix(typ, string(PositionBody)) || strings.HasSuffix(typ, "Form") { + position = PositionBody + } + if strings.HasSuffix(typ, string(PositionHeader)) { + position = PositionHeader + } + typ = strings.TrimPrefix(typ, "*") + + for _, name := range param.Names { + params = append(params, ParamDefinition{ + Name: name.Name, + Type: typ, + Position: position, + }) + } + } + + actions[recvType] = append(actions[recvType], ActionDefinition{ + Route: path, + Method: strings.ToUpper(method), + Name: decl.Name.Name, + HasData: len(decl.Type.Results.List) > 1, + Params: params, + }) + } + + var items []RouteDefinition + for k, item := range routes { + a, ok := actions[k] + if !ok { + continue + } + item.Actions = a + item.Imports = []string{} + if im, ok := usedImports[k]; ok { + item.Imports = lo.Uniq(im) + } + items = append(items, item) + } + return items +} + +func parseRouteComment(line string) (string, string, error) { + pattern := regexp.MustCompile(`(?mi)@router\s+(.*?)\s+\[(.*?)\]`) + submatch := pattern.FindStringSubmatch(line) + + if len(submatch) != 3 { + return "", "", errors.New("invalid route definition") + } + + return submatch[1], submatch[2], nil +} + +func getPackageRoute(mod, path string) string { + paths := strings.SplitN(path, "modules", 2) + pkg := paths[1] + // path可能值为 + // /test/user_controller.go + // /test/modules/user_controller.go + + return strings.TrimLeft(filepath.Dir(pkg), "/") +} + +func formatRoute(route string) string { + pattern := regexp.MustCompile(`(?mi)\{(.*?)\}`) + if !pattern.MatchString(route) { + return route + } + + items := pattern.FindAllStringSubmatch(route, -1) + for _, item := range items { + param := strcase.ToLowerCamel(item[1]) + route = strings.ReplaceAll(route, item[0], fmt.Sprintf("{%s}", param)) + } + + route = pattern.ReplaceAllString(route, ":$1") + route = strings.ReplaceAll(route, "/:id", "/:id") + route = strings.ReplaceAll(route, "Id/", "Id/") + return route +} diff --git a/templates/module/controller.go.tpl b/templates/module/controller.go.tpl index d2318eb..39512d2 100644 --- a/templates/module/controller.go.tpl +++ b/templates/module/controller.go.tpl @@ -14,3 +14,17 @@ func (c *Controller) Prepare() error { c.log = log.WithField("module", "{{.ModuleName}}.Controller") return nil } + +// Test godoc +// +// @Summary Test +// @Description Test +// @Tags Test +// @Accept json +// @Produce json +// @Param id path int true "AccountID" +// @Param queryFilter query dto.AlarmListQuery true "AlarmListQueryFilter" +// @Param pageFilter query common.PageQueryFilter true "PageQueryFilter" +// @Param sortFilter query common.SortQueryFilter true "SortQueryFilter" +// @Success 200 {object} common.PageDataResponse{list=dto.AlarmItem} +// @Router /v1/test//{id} [get] \ No newline at end of file diff --git a/templates/project/app/console/-gitkeep.tpl b/templates/project/app/console/-gitkeep.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/project/app/errorx/-gitkeep.tpl b/templates/project/app/errorx/-gitkeep.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/project/app/events/-gitkeep.tpl b/templates/project/app/events/-gitkeep.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/project/app/http/-gitkeep.tpl b/templates/project/app/http/-gitkeep.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/project/app/jobs/-gitkeep.tpl b/templates/project/app/jobs/-gitkeep.tpl new file mode 100644 index 0000000..e69de29 diff --git a/templates/project/pkg/f/bind.go.tpl b/templates/project/pkg/f/bind.go.tpl new file mode 100644 index 0000000..81b5a71 --- /dev/null +++ b/templates/project/pkg/f/bind.go.tpl @@ -0,0 +1,69 @@ +package f + +import ( + "github.com/gofiber/fiber/v3" +) + + +func Path[T fiber.GenericType](key string) func(fiber.Ctx) (T, error) { + return func(ctx fiber.Ctx) (T, error) { + v := fiber.Params[T](ctx, key) + return v, nil + } +} + +func URI[T any]() func(fiber.Ctx) (*T, error) { + return func(ctx fiber.Ctx) (*T, error) { + p := new(T) + if err := ctx.Bind().URI(p); err != nil { + return nil, err + } + + return p, nil + } +} + +func Cookie[T any]() func(fiber.Ctx) (*T, error) { + return func(ctx fiber.Ctx) (*T, error) { + p := new(T) + if err := ctx.Bind().Cookie(p); err != nil { + return nil, err + } + + return p, nil + } +} + +func Body[T any]() func(fiber.Ctx) (*T, error) { + return func(ctx fiber.Ctx) (*T, error) { + p := new(T) + if err := ctx.Bind().Body(p); err != nil { + return nil, err + } + + return p, nil + } +} + +func Query[T any]() func(fiber.Ctx) (*T, error) { + return func(ctx fiber.Ctx) (*T, error) { + p := new(T) + if err := ctx.Bind().Query(p); err != nil { + return nil, err + } + + return p, nil + } +} + +func Header[T any]() func(fiber.Ctx) (*T, error) { + return func(ctx fiber.Ctx) (*T, error) { + p := new(T) + err := ctx.Bind().Header(p) + if err != nil { + return nil, err + } + + return p, nil + } +} diff --git a/templates/project/pkg/f/func.go.tpl b/templates/project/pkg/f/func.go.tpl new file mode 100644 index 0000000..b6c1158 --- /dev/null +++ b/templates/project/pkg/f/func.go.tpl @@ -0,0 +1,194 @@ +package f + +import ( + "github.com/gofiber/fiber/v3" +) + +func Func(f fiber.Handler) fiber.Handler { + return f +} + +func Func1[P1 any]( + f func(fiber.Ctx, P1) error, + pf1 func(fiber.Ctx) (P1, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p, err := pf1(ctx) + if err != nil { + return err + } + + err = f(ctx, p) + if err != nil { + return err + } + return nil + } +} + +func Func2[P1 any, P2 any]( + f func(fiber.Ctx, P1, P2) error, + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return err + } + + p2, err := pf2(ctx) + if err != nil { + return err + } + + err = f(ctx, p1, p2) + if err != nil { + return err + } + return nil + } +} + +func Func3[P1 any, P2 any, P3 any]( + f func(fiber.Ctx, P1, P2, P3) error, + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + err = f(ctx, p1, p2, p3) + if err != nil { + return nil + } + return nil + } +} + +func Func4[P1 any, P2 any, P3 any, P4 any]( + f func(fiber.Ctx, P1, P2, P3, P4) error, + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + + p2, err := pf2(ctx) + if err != nil { + return nil + } + + p3, err := pf3(ctx) + if err != nil { + return nil + } + + p4, err := pf4(ctx) + if err != nil { + return nil + } + + err = f(ctx, p1, p2, p3, p4) + if err != nil { + return nil + } + return nil + } +} + +func Func5[P1 any, P2 any, P3 any, P4 any, P5 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5) error, + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + err = f(ctx, p1, p2, p3, p4, p5) + if err != nil { + return nil + } + return nil + } +} + +func Func6[P1 any, P2 any, P3 any, P4 any, P5 any, P6 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5, P6) error, + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), + pf6 func(fiber.Ctx) (P6, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + p6, err := pf6(ctx) + if err != nil { + return nil + } + err = f(ctx, p1, p2, p3, p4, p5, p6) + if err != nil { + return nil + } + return nil + } +} diff --git a/templates/project/pkg/f/func_data.go.tpl b/templates/project/pkg/f/func_data.go.tpl new file mode 100644 index 0000000..8eeb68a --- /dev/null +++ b/templates/project/pkg/f/func_data.go.tpl @@ -0,0 +1,413 @@ +package f + +import ( + "github.com/gofiber/fiber/v3" +) + +func DataFunc[T any]( + f func(fiber.Ctx) (T, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + data, err := f(ctx) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc1[T any, P1 any]( + f func(fiber.Ctx, P1) (T, error), + pf1 func(fiber.Ctx) (P1, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p, err := pf1(ctx) + if err != nil { + return nil + } + + data, err := f(ctx, p) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc2[T any, P1 any, P2 any]( + f func(fiber.Ctx, P1, P2) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc3[T any, P1 any, P2 any, P3 any]( + f func(fiber.Ctx, P1, P2, P3) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc4[T any, P1 any, P2 any, P3 any, P4 any]( + f func(fiber.Ctx, P1, P2, P3, P4) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc5[T any, P1 any, P2 any, P3 any, P4 any, P5 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4, p5) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc6[T any, P1 any, P2 any, P3 any, P4 any, P5 any, P6 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5, P6) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), + pf6 func(fiber.Ctx) (P6, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + p6, err := pf6(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4, p5, p6) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc7[T any, P1 any, P2 any, P3 any, P4 any, P5 any, P6 any, P7 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), + pf6 func(fiber.Ctx) (P6, error), + pf7 func(fiber.Ctx) (P7, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + p6, err := pf6(ctx) + if err != nil { + return nil + } + p7, err := pf7(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc8[T any, P1 any, P2 any, P3 any, P4 any, P5 any, P6 any, P7 any, P8 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), + pf6 func(fiber.Ctx) (P6, error), + pf7 func(fiber.Ctx) (P7, error), + pf8 func(fiber.Ctx) (P8, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + p6, err := pf6(ctx) + if err != nil { + return nil + } + p7, err := pf7(ctx) + if err != nil { + return nil + } + p8, err := pf8(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7, p8) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc9[T any, P1 any, P2 any, P3 any, P4 any, P5 any, P6 any, P7 any, P8 any, P9 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8, P9) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), + pf6 func(fiber.Ctx) (P6, error), + pf7 func(fiber.Ctx) (P7, error), + pf8 func(fiber.Ctx) (P8, error), + pf9 func(fiber.Ctx) (P9, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + p6, err := pf6(ctx) + if err != nil { + return nil + } + p7, err := pf7(ctx) + if err != nil { + return nil + } + p8, err := pf8(ctx) + if err != nil { + return nil + } + p9, err := pf9(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7, p8, p9) + if err != nil { + return nil + } + return ctx.JSON(data) + } +} + +func DataFunc10[T any, P1 any, P2 any, P3 any, P4 any, P5 any, P6 any, P7 any, P8 any, P9 any, P10 any]( + f func(fiber.Ctx, P1, P2, P3, P4, P5, P6, P7, P8, P9, P10) (T, error), + pf1 func(fiber.Ctx) (P1, error), + pf2 func(fiber.Ctx) (P2, error), + pf3 func(fiber.Ctx) (P3, error), + pf4 func(fiber.Ctx) (P4, error), + pf5 func(fiber.Ctx) (P5, error), + pf6 func(fiber.Ctx) (P6, error), + pf7 func(fiber.Ctx) (P7, error), + pf8 func(fiber.Ctx) (P8, error), + pf9 func(fiber.Ctx) (P9, error), + pf10 func(fiber.Ctx) (P10, error), +) fiber.Handler { + return func(ctx fiber.Ctx) error { + p1, err := pf1(ctx) + if err != nil { + return nil + } + p2, err := pf2(ctx) + if err != nil { + return nil + } + p3, err := pf3(ctx) + if err != nil { + return nil + } + p4, err := pf4(ctx) + if err != nil { + return nil + } + p5, err := pf5(ctx) + if err != nil { + return nil + } + p6, err := pf6(ctx) + if err != nil { + return nil + } + p7, err := pf7(ctx) + if err != nil { + return nil + } + p8, err := pf8(ctx) + if err != nil { + return nil + } + p9, err := pf9(ctx) + if err != nil { + return nil + } + p10, err := pf10(ctx) + if err != nil { + return nil + } + data, err := f(ctx, p1, p2, p3, p4, p5, p6, p7, p8, p9, p10) + if err != nil { + return nil + } + return ctx.JSON(data) + } +}