diff --git a/cmd/new.go b/cmd/new.go new file mode 100644 index 0000000..0077cbf --- /dev/null +++ b/cmd/new.go @@ -0,0 +1,25 @@ +package cmd + +import ( + "github.com/spf13/cobra" +) + +func CommandInit(root *cobra.Command) { + cmd := &cobra.Command{ + Use: "new [project|module]", + Short: "new project/module", + } + + cmd.PersistentFlags().BoolP("force", "f", false, "Force init project if exists") + + cmds := []func(*cobra.Command){ + CommandNewProject, + CommandNewModule, + } + + for _, c := range cmds { + c(cmd) + } + + root.AddCommand(cmd) +} diff --git a/cmd/new_module.go b/cmd/new_module.go new file mode 100644 index 0000000..b96e50b --- /dev/null +++ b/cmd/new_module.go @@ -0,0 +1,94 @@ +package cmd + +import ( + "fmt" + "io/fs" + "os" + "path/filepath" + "strings" + "text/template" + + "git.ipao.vip/rogeecn/atomctl/templates" + "github.com/samber/lo" + log "github.com/sirupsen/logrus" + "github.com/spf13/cobra" +) + +func CommandNewModule(root *cobra.Command) { + cmd := &cobra.Command{ + Use: "module", + Short: "new module", + Args: cobra.ExactArgs(1), + RunE: commandNewModuleE, + } + + root.AddCommand(cmd) +} + +func commandNewModuleE(cmd *cobra.Command, args []string) error { + module := lo.Filter(strings.Split(args[0], "."), func(s string, _ int) bool { + return s != "" + }) + + modulePath := module[0] + if len(module) > 1 { + modulePath = strings.Join(module, "/modules/") + } + moduleName := module[len(module)-1] + modulePath = filepath.Join("modules", modulePath) + log.Infof("new module: %s", modulePath) + + force, _ := cmd.Flags().GetBool("force") + if _, err := os.Stat(modulePath); err == nil { + if !force { + return fmt.Errorf("module directory %s already exists", modulePath) + } + log.Warnf("强制删除已存在的目录: %s", modulePath) + if err := os.RemoveAll(modulePath); err != nil { + return fmt.Errorf("failed to remove existing directory: %v", err) + } + } + + err := os.MkdirAll(modulePath, os.ModePerm) + if err != nil { + return err + } + + err = fs.WalkDir(templates.Module, "module", func(path string, d fs.DirEntry, err error) error { + if err != nil { + return err + } + if d.IsDir() { + return nil + } + + relPath, err := filepath.Rel("module", path) + if err != nil { + return err + } + + destPath := filepath.Join(modulePath, strings.TrimSuffix(relPath, ".tpl")) + destDir := filepath.Dir(destPath) + err = os.MkdirAll(destDir, os.ModePerm) + if err != nil { + return err + } + + tmpl, err := template.ParseFS(templates.Module, path) + if err != nil { + return err + } + + destFile, err := os.Create(destPath) + if err != nil { + return err + } + defer destFile.Close() + + return tmpl.Execute(destFile, map[string]string{ + "ModuleName": moduleName, + }) + }) + + return err +} diff --git a/cmd/init.go b/cmd/new_project.go similarity index 92% rename from cmd/init.go rename to cmd/new_project.go index fd7e712..5fd2979 100644 --- a/cmd/init.go +++ b/cmd/new_project.go @@ -22,19 +22,18 @@ func isValidGoPackageName(name string) bool { return goPackageRegexp.MatchString(name) } -func CommandInit(root *cobra.Command) { +func CommandNewProject(root *cobra.Command) { cmd := &cobra.Command{ - Use: "init [project]", - Short: "init new project", + Use: "project", + Short: "new project", Args: cobra.ExactArgs(1), - RunE: commandInitE, + RunE: commandNewProjectE, } - cmd.Flags().BoolP("force", "f", false, "Force init project if exists") root.AddCommand(cmd) } -func commandInitE(cmd *cobra.Command, args []string) error { +func commandNewProjectE(cmd *cobra.Command, args []string) error { moduleName := args[0] if !isValidGoPackageName(moduleName) { return fmt.Errorf("invalid module name: %s, should be a valid go package name", moduleName) @@ -42,8 +41,6 @@ func commandInitE(cmd *cobra.Command, args []string) error { log.Info("创建项目: ", moduleName) - force, _ := cmd.Flags().GetBool("force") - var projectInfo struct { ModuleName string ProjectName string @@ -54,6 +51,7 @@ func commandInitE(cmd *cobra.Command, args []string) error { projectInfo.ProjectName = moduleSplitInfo[len(moduleSplitInfo)-1] // 检查目录是否存在 + force, _ := cmd.Flags().GetBool("force") if _, err := os.Stat(projectInfo.ProjectName); err == nil { if !force { return fmt.Errorf("project directory %s already exists", projectInfo.ProjectName) diff --git a/templates/module/controller.go.tpl b/templates/module/controller.go.tpl new file mode 100644 index 0000000..d2318eb --- /dev/null +++ b/templates/module/controller.go.tpl @@ -0,0 +1,16 @@ +package {{.ModuleName}} + +import ( + log "github.com/sirupsen/logrus" +) + +// @provider +type Controller struct { + svc *Service + log *log.Entry `inject:"false"` +} + +func (c *Controller) Prepare() error { + c.log = log.WithField("module", "{{.ModuleName}}.Controller") + return nil +} diff --git a/templates/module/dto.go.tpl b/templates/module/dto.go.tpl new file mode 100644 index 0000000..f54de4f --- /dev/null +++ b/templates/module/dto.go.tpl @@ -0,0 +1 @@ +package {{.ModuleName}} diff --git a/templates/module/provider.gen.go.tpl b/templates/module/provider.gen.go.tpl new file mode 100755 index 0000000..bfd91d7 --- /dev/null +++ b/templates/module/provider.gen.go.tpl @@ -0,0 +1,9 @@ +package {{.ModuleName}} + +import ( + "git.ipao.vip/rogeecn/atom/utils/opt" +) + +func Provide(opts ...opt.Option) error { + return nil +} diff --git a/templates/module/router.go.tpl b/templates/module/router.go.tpl new file mode 100755 index 0000000..cdd0774 --- /dev/null +++ b/templates/module/router.go.tpl @@ -0,0 +1,29 @@ +package {{.ModuleName}} + +import ( + _ "git.ipao.vip/rogeecn/atom" + _ "git.ipao.vip/rogeecn/atom/contracts" + "github.com/gofiber/fiber/v3" + log "github.com/sirupsen/logrus" +) + +// @provider:except contracts.HttpRoute atom.GroupRoutes +type Router struct { + log *log.Entry `inject:"false"` + + controller *Controller +} + +func (r *Router) Name() string { + return "{{.ModuleName}}" +} + +func (r *Router) Prepare() error { + r.log = log.WithField("http.group", r.Name()) + return nil +} + +func (r *Router) Register(router fiber.Router) { + group := router.Group(r.Name()) + _ = group +} diff --git a/templates/module/service.go.tpl b/templates/module/service.go.tpl new file mode 100644 index 0000000..6babc57 --- /dev/null +++ b/templates/module/service.go.tpl @@ -0,0 +1,20 @@ +package {{.ModuleName}} + +import ( + "database/sql" + + . "github.com/go-jet/jet/v2/postgres" + log "github.com/sirupsen/logrus" +) + +// @provider:except +type Service struct { + db *sql.DB + log *log.Entry `inject:"false"` +} + +func (svc *Service) Prepare() error { + svc.log = log.WithField("module", "{{.ModuleName}}.service") + _ = Int(1) + return nil +} diff --git a/templates/module/service_test.go.tpl b/templates/module/service_test.go.tpl new file mode 100644 index 0000000..3498f9f --- /dev/null +++ b/templates/module/service_test.go.tpl @@ -0,0 +1,37 @@ +package {{.ModuleName}} + +import ( + "testing" + + "backend/pkg/service/testx" + + . "github.com/smartystreets/goconvey/convey" + "github.com/stretchr/testify/suite" + "go.uber.org/dig" +) + +type ServiceInjectParams struct { + dig.In + Svc *Service +} + +type ServiceTestSuite struct { + suite.Suite + ServiceInjectParams +} + +func Test_DiscoverMedias(t *testing.T) { + providers := testx.Default().With( + Provide, + ) + + testx.Serve(providers, t, func(params ServiceInjectParams) { + suite.Run(t, &ServiceTestSuite{ServiceInjectParams: params}) + }) +} + +func (s *ServiceTestSuite) Test_Service() { + Convey("Test Service", s.T(), func() { + So(s.Svc, ShouldNotBeNil) + }) +} diff --git a/templates/templates.go b/templates/templates.go index 9a63a27..743be29 100644 --- a/templates/templates.go +++ b/templates/templates.go @@ -4,3 +4,6 @@ import "embed" //go:embed project var Project embed.FS + +//go:embed module +var Module embed.FS