From 1f75148543717b3e493ed27ace1e71e578317c3e Mon Sep 17 00:00:00 2001 From: nikolahellatrigger <0xF7A4C6@proton.me> Date: Tue, 19 Dec 2023 12:53:14 +0100 Subject: [PATCH] thoriqadillah + error handling/file creation --- go.mod | 7 +- go.sum | 10 ++ slick/cmd.go | 35 +++++++ slick/main.go | 248 ++++++++++++++++++++++++++++++++------------------ 4 files changed, 210 insertions(+), 90 deletions(-) create mode 100644 slick/cmd.go diff --git a/go.mod b/go.mod index fae664a..17aab5d 100644 --- a/go.mod +++ b/go.mod @@ -1,10 +1,13 @@ module github.com/anthdm/slick -go 1.21.0 +go 1.21 require ( github.com/a-h/templ v0.2.476 github.com/julienschmidt/httprouter v1.3.0 + github.com/joho/godotenv v1.5.1 + github.com/spf13/cobra v1.8.0 + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect ) -require github.com/joho/godotenv v1.5.1 diff --git a/go.sum b/go.sum index 1a163ab..642ebf6 100644 --- a/go.sum +++ b/go.sum @@ -1,8 +1,18 @@ github.com/a-h/templ v0.2.476 h1:+H4hP4CwK4kfJwXsE6kHeFWMGtcVOVoOm/I64uzARBk= github.com/a-h/templ v0.2.476/go.mod h1:zQ95mSyadNTGHv6k5Fm+wQU8zkBMMbHCHg7eAvUZKNM= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= +github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U= github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= +github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= +github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/slick/cmd.go b/slick/cmd.go new file mode 100644 index 0000000..194e03e --- /dev/null +++ b/slick/cmd.go @@ -0,0 +1,35 @@ +package main + +import ( + "github.com/spf13/cobra" +) + +type commandFunc func() *cobra.Command + +type cli struct { + cmds []commandFunc +} + +func NewCommand() *cli { + return &cli{ + cmds: make([]commandFunc, 0), + } +} + +func (c *cli) Register(cmds ...commandFunc) { + c.cmds = append(c.cmds, cmds...) +} + +func (c *cli) Execute() { + rootCmd := &cobra.Command{ + Use: "slick", + Short: "Slick CLI", + Long: "Slick web framework", + } + + for _, command := range c.cmds { + rootCmd.AddCommand(command()) + } + + rootCmd.Execute() +} diff --git a/slick/main.go b/slick/main.go index 2c8ff83..6162d5d 100644 --- a/slick/main.go +++ b/slick/main.go @@ -6,111 +6,182 @@ import ( "os/exec" "strings" "time" -) -func usage() { - fmt.Println("help....") - os.Exit(0) -} + "github.com/spf13/cobra" +) -func main() { - args := os.Args - if len(args) < 2 { - usage() - } - cmd := os.Args[1] - - switch cmd { - case "run": - if _, err := os.Stat("cmd/main.go"); err != nil { - fmt.Println("not in slick app root: cmd/main.go not found") - os.Exit(1) - } - if err := exec.Command("templ", "generate").Run(); err != nil { - fmt.Println(err) - os.Exit(1) - } - exec.Command("go", "run", "cmd/main.go").Run() - case "install": - if err := installProject(); err != nil { - fmt.Println(err) - } - case "new": - if len(os.Args) != 3 { - usage() - } - name := os.Args[2] - if err := generateProject(name); err != nil { - fmt.Println(err) - } - } +type File struct { + Path string + Content []byte } -func generateProject(name string) error { - fmt.Println("creating new slick project:", name) - if err := os.Mkdir(name, os.ModePerm); err != nil { +func writeFileWithCheck(file File) error { + if err := os.WriteFile(file.Path, file.Content, os.ModePerm); err != nil { return err } - folders := []string{"model", "handler", "view", "cmd", "public"} + return nil +} - for _, folder := range folders { - if err := os.Mkdir(name+"/"+folder, os.ModePerm); err != nil { - return err - } - } +func main() { + cmd := NewCommand() + cmd.Register( + runProject, + installProject, + generateProject, + generateModel, + generateView, + generateHandler, + ) + + cmd.Execute() +} - if err := os.WriteFile(name+"/go.mod", writeGoModContents(name), os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/.air.toml", writeAirTomlContents(), os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/.env", writeEnvFileContents(), os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/.gitignore", writeGitignore(), os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/public/app.css", []byte(""), os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/cmd/main.go", writeMainContents(name), os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/handler/hello.go", writeHandlerContent(name), os.ModePerm); err != nil { - return err - } - if err := os.Mkdir(name+"/view/hello", os.ModePerm); err != nil { - return err - } - if err := os.Mkdir(name+"/view/layout", os.ModePerm); err != nil { - return err - } - if err := os.WriteFile(name+"/view/layout/base.templ", writeBaseLayoutContent(), os.ModePerm); err != nil { - return err +func runProject() *cobra.Command { + return &cobra.Command{ + Use: "run", + Example: "slick run", + Short: "Run slick development server", + Run: func(cmd *cobra.Command, args []string) { + if _, err := os.Stat("cmd/main.go"); err != nil { + fmt.Println("not in slick app root: cmd/main.go not found") + return + } + if err := exec.Command("templ", "generate").Run(); err != nil { + fmt.Println(err) + return + } + + if err := exec.Command("go", "run", "cmd/main.go").Run(); err != nil { + fmt.Println(err) + } + }, } - if err := os.WriteFile(name+"/view/hello/hello.templ", writeViewContent(name), os.ModePerm); err != nil { - return err +} + +func installProject() *cobra.Command { + return &cobra.Command{ + Use: "install", + Aliases: []string{"i"}, + Example: "slick install", + Short: "Install project's dependency", + Run: func(cmd *cobra.Command, args []string) { + start := time.Now() + fmt.Println("installing project...") + if err := exec.Command("go", "get", "github.com/anthdm/slick@latest").Run(); err != nil { + fmt.Println(err) + return + } + + if err := exec.Command("go", "get", "github.com/a-h/templ").Run(); err != nil { + fmt.Println(err) + return + } + if err := exec.Command("templ", "generate").Run(); err != nil { + fmt.Println(err) + return + } + + fmt.Printf("done installing project in %v\n", time.Since(start)) + }, } +} - return nil +func generateProject() *cobra.Command { + return &cobra.Command{ + Use: "new", + Example: "slick new hello-world", + Short: "Create new slick project", + Run: func(cmd *cobra.Command, args []string) { + if len(args) == 0 { + fmt.Println("invalid arguments") + return + } + + name := args[0] + + fmt.Println("creating new slick project:", name) + if err := os.Mkdir(name, os.ModePerm); err != nil { + fmt.Println(err) + return + } + + files := []File{ + // setup directory + {Path: name + "/model", Content: nil}, + {Path: name + "/handler", Content: nil}, + {Path: name + "/view", Content: nil}, + {Path: name + "/cmd", Content: nil}, + {Path: name + "/public", Content: nil}, + {Path: name + "/view/hello", Content: nil}, + {Path: name + "/view/layout", Content: nil}, + + // setup files + {Path: name + "/go.mod", Content: writeGoModContents(name)}, + {Path: name + "/.air.toml", Content: writeAirTomlContents()}, + {Path: name + "/.env", Content: writeEnvFileContents()}, + {Path: name + "/.gitignore", Content: writeGitignore()}, + {Path: name + "/public/app.css", Content: []byte("")}, + {Path: name + "/cmd/main.go", Content: writeMainContents(name)}, + {Path: name + "/handler/hello.go", Content: writeHandlerContent(name)}, + {Path: name + "/view/layout/base.templ", Content: writeBaseLayoutContent()}, + {Path: name + "/view/hello/hello.templ", Content: writeViewContent(name)}, + } + + errors := []error{} + for _, file := range files { + if file.Content == nil { + if err := os.Mkdir(file.Path, os.ModePerm); err != nil { + errors = append(errors, err) + } + } else { + if err := writeFileWithCheck(file); err != nil { + errors = append(errors, err) + } + } + } + + if len(errors) != 0 { + fmt.Println("slick encountered errors during file initialization:", errors) + return + } + }, + } } -func installProject() error { - start := time.Now() - fmt.Println("installing project...") - if err := exec.Command("go", "get", "github.com/anthdm/slick@latest").Run(); err != nil { - return err +func generateModel() *cobra.Command { + return &cobra.Command{ + Use: "model", + Example: "slick model user", + Short: "Generate new model", + Run: func(cmd *cobra.Command, args []string) { + // TODO: + }, } - if err := exec.Command("go", "get", "github.com/a-h/templ").Run(); err != nil { - return err +} + +func generateView() *cobra.Command { + return &cobra.Command{ + Use: "view", + Example: "slick view user", + Short: "Generate new view", + Run: func(cmd *cobra.Command, args []string) { + // TODO: + + }, } - if err := exec.Command("templ", "generate").Run(); err != nil { - return err +} + +func generateHandler() *cobra.Command { + return &cobra.Command{ + Use: "handler", + Example: "slick handler home", + Short: "Generate new handler", + Run: func(cmd *cobra.Command, args []string) { + // TODO: + + }, } - fmt.Printf("done installing project in %v\n", time.Since(start)) - return nil } func writeEnvFileContents() []byte { @@ -130,6 +201,7 @@ func writeMainContents(mod string) []byte { package main import ( + "log" "github.com/anthdm/slick" "%s/handler" )