diff --git a/README.md b/README.md index 7ff9b9c..11797e8 100644 --- a/README.md +++ b/README.md @@ -44,15 +44,15 @@ Fir sits somewhere between [Phoenix Liveview](https://github.com/phoenixframewo ## CLI -You don't need this to get started but the the cli can be used to generate the boilerplate: +You don't need this to get started but the the cli can be used to generate a simple quickstart boilerplate: ```go -go run github.com/livefir/fir/cli gen project -n quickstart // generates a folder named quickstart +go run github.com/livefir/cli gen project -n quickstart // generates a folder named quickstart cd quickstart go run main.go open localhost:9867 -go run github.com/livefir/fir/cli gen route -n index // generates a new route +go run github.com/livefir/cli gen route -n index // generates a new route ``` diff --git a/cli/LICENSE b/cli/LICENSE deleted file mode 100644 index 3b4068b..0000000 --- a/cli/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright © 2022 Adnaan Badr badr.adnaan@gmail.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. diff --git a/cli/README.md b/cli/README.md deleted file mode 100644 index b016d30..0000000 --- a/cli/README.md +++ /dev/null @@ -1,2 +0,0 @@ - -`go run github.com/livefir/fir/cli` \ No newline at end of file diff --git a/cli/cmd/gen.go b/cli/cmd/gen.go deleted file mode 100644 index 4d189ed..0000000 --- a/cli/cmd/gen.go +++ /dev/null @@ -1,15 +0,0 @@ -package cmd - -import "github.com/spf13/cobra" - -var gendCmd = &cobra.Command{ - Use: "gen", - Short: "Generates fir bolilerplate", - Long: `The gen command generates files and directories for a fir project. It has subcommands.`, -} - -func init() { - rootCmd.AddCommand(gendCmd) - gendCmd.AddCommand(projectCmd) - gendCmd.AddCommand(routeCmd) -} diff --git a/cli/cmd/project.go b/cli/cmd/project.go deleted file mode 100644 index ad2777b..0000000 --- a/cli/cmd/project.go +++ /dev/null @@ -1,24 +0,0 @@ -package cmd - -import ( - "github.com/livefir/fir/cli/gen" - "github.com/spf13/cobra" -) - -var ( - projectName string -) - -// projectCmd represents the new command -var projectCmd = &cobra.Command{ - Use: "project", - Short: "Creates a new fir project", - Long: `Creates a new fir project`, - Run: func(cmd *cobra.Command, args []string) { - gen.NewProject(projectName) - }, -} - -func init() { - projectCmd.Flags().StringVarP(&projectName, "name", "n", "quickstart", "name of the project") -} diff --git a/cli/cmd/public.go b/cli/cmd/public.go deleted file mode 100644 index 304a3ee..0000000 --- a/cli/cmd/public.go +++ /dev/null @@ -1,50 +0,0 @@ -package cmd - -import ( - "fmt" - "os" - - "github.com/livefir/fir/gen" - "github.com/spf13/cobra" -) - -var ( - inDir string - outDir string - extensions []string -) - -// publicCmd represents the public command -var publicCmd = &cobra.Command{ - Use: "public", - Short: "Generates the public folder containing the html files", - Long: `The public command generates a public folder containing the html files in the project. - It preserves the paths of the html files enabling a flexible project structure. The generated public directory - can be embedded in the binary as is.`, - Run: func(cmd *cobra.Command, args []string) { - var opts []gen.PublicDirOption - if inDir != "" { - opts = append(opts, gen.InDir(inDir)) - } - - if outDir != "" { - opts = append(opts, gen.OutDir(outDir)) - } - - if len(extensions) != 0 { - opts = append(opts, gen.PublicFileExtensions(extensions)) - } - - if err := gen.GeneratePublicDir(opts...); err != nil { - fmt.Println(err) - os.Exit(1) - } - }, -} - -func init() { - rootCmd.AddCommand(publicCmd) - publicCmd.Flags().StringVarP(&inDir, "in", "i", "", "path to input directory which contains the html template files") - publicCmd.Flags().StringVarP(&outDir, "out", "o", "", "path to output directory") - publicCmd.Flags().StringSliceVarP(&extensions, "extensions", "x", nil, "comma separated list of template exatensions e.g. .html,.tmpl") -} diff --git a/cli/cmd/root.go b/cli/cmd/root.go deleted file mode 100644 index 24f5ce2..0000000 --- a/cli/cmd/root.go +++ /dev/null @@ -1,38 +0,0 @@ -package cmd - -import ( - "os" - - "github.com/spf13/cobra" -) - -// rootCmd represents the base command when called without any subcommands -var rootCmd = &cobra.Command{ - Use: "fir", - Short: "A cli for the Fir web framework", - Long: ``, - // Uncomment the following line if your bare application - // has an action associated with it: - // Run: func(cmd *cobra.Command, args []string) { }, -} - -// Execute adds all child commands to the root command and sets flags appropriately. -// This is called by main.main(). It only needs to happen once to the rootCmd. -func Execute() { - err := rootCmd.Execute() - if err != nil { - os.Exit(1) - } -} - -func init() { - // Here you will define your flags and configuration settings. - // Cobra supports persistent flags, which, if defined here, - // will be global for your application. - - // rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cli.yaml)") - - // Cobra also supports local flags, which will only run - // when this action is called directly. - rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") -} diff --git a/cli/cmd/route.go b/cli/cmd/route.go deleted file mode 100644 index 68d4552..0000000 --- a/cli/cmd/route.go +++ /dev/null @@ -1,24 +0,0 @@ -package cmd - -import ( - "github.com/livefir/fir/cli/gen" - "github.com/spf13/cobra" -) - -var ( - routeName string -) - -// routeCmd represents the new command -var routeCmd = &cobra.Command{ - Use: "route", - Short: "Creates a new fir route", - Long: `Creates a new fir route`, - Run: func(cmd *cobra.Command, args []string) { - gen.NewRoute(routeName) - }, -} - -func init() { - routeCmd.Flags().StringVarP(&routeName, "name", "n", "index", "route name") -} diff --git a/cli/cmd/secret.go b/cli/cmd/secret.go deleted file mode 100644 index 9b70f22..0000000 --- a/cli/cmd/secret.go +++ /dev/null @@ -1,30 +0,0 @@ -package cmd - -import ( - "encoding/hex" - "fmt" - - "github.com/gorilla/securecookie" - "github.com/spf13/cobra" -) - -var size int - -// secretCmd generates a secret key using securecookie.GenerateRandomKey -var secretCmd = &cobra.Command{ - Use: "secret", - Short: "Generates a hex secret key", - Long: `Generates a hex secret key for securecookie.GenerateRandomKey. - This can be used with fir.WithSessionSecrets to set the session secret key. The default size is 32. - Please refer to: https://pkg.go.dev/github.com/gorilla/securecookie#New for more information.`, - Run: func(cmd *cobra.Command, args []string) { - key := securecookie.GenerateRandomKey(size) - hexKey := hex.EncodeToString(key) - fmt.Println(hexKey) - }, -} - -func init() { - rootCmd.AddCommand(secretCmd) - secretCmd.Flags().IntVarP(&size, "size", "s", 32, "size of the secret key") -} diff --git a/cli/gen/gen.go b/cli/gen/gen.go deleted file mode 100644 index dab6613..0000000 --- a/cli/gen/gen.go +++ /dev/null @@ -1,139 +0,0 @@ -package gen - -import ( - "bytes" - "embed" - "fmt" - "go/format" - "io/fs" - "log" - "os" - "path/filepath" - "strings" - "text/template" - - "github.com/Masterminds/sprig/v3" - "github.com/yosssi/gohtml" - "golang.org/x/text/cases" - "golang.org/x/text/language" -) - -var simpleAssetsPath = "simple_assets" -var routesAssetsPath = "routes_assets" - -//go:embed simple_assets/* -var simpleAssets embed.FS - -//go:embed routes_assets/* -var routesAssets embed.FS - -func NewProject(projectName string) { - fs.WalkDir(simpleAssets, simpleAssetsPath, func(path string, d fs.DirEntry, err error) error { - if err != nil { - log.Fatal(err) - } - outPath := strings.TrimPrefix(path, simpleAssetsPath) - outPath = strings.TrimSuffix(outPath, ".str") - outPath = filepath.Join(projectName, outPath) - - if d.IsDir() { - if err := os.MkdirAll(outPath, os.ModePerm); err != nil { - return err - } - return nil - } - - execTextTemplate(path, outPath, simpleAssets, map[string]any{"projectName": projectName}) - return nil - }) - - fmt.Printf("Generated project: %v\n", projectName) - fmt.Printf(` -To run the project: - -cd %v -go run main.go - -`, projectName) - -} - -func NewRoute(routeName string) { - routeName = strings.TrimSpace(routeName) - routeNameTitle := cases.Title(language.English).String(routeName) - routeNameLower := cases.Lower(language.English).String(routeName) - - fs.WalkDir(routesAssets, routesAssetsPath, func(path string, d fs.DirEntry, err error) error { - if err != nil { - log.Fatal(err) - } - - outPath := strings.TrimPrefix(path, routesAssetsPath) - outPath = strings.TrimSuffix(outPath, ".str") - outPath = filepath.Join("routes", outPath) - outPath = strings.Replace(outPath, "route.", routeNameLower+".", -1) - - if d.IsDir() { - if err := os.MkdirAll(outPath, os.ModePerm); err != nil { - return err - } - return nil - } - - execTextTemplate(path, outPath, routesAssets, map[string]any{ - "route": routeNameTitle, - "routeLower": routeNameLower, - }) - return nil - }) - - // add route to the http handler - fmt.Printf(` -Generated route: %v -To add the route to the http handler, add the following line to the http handler: - -http.Handle("/%v", controller.RouteFunc(routes.%v)) - -`, - routeNameLower, routeNameLower, routeNameTitle) - -} - -func execTextTemplate(inFile, outFile string, embedfs embed.FS, vars map[string]any) { - inFileData, err := embedfs.ReadFile(inFile) - checkerr(err) - - t := template.Must( - template.New("gen"). - Delims("[[", "]]"). - Funcs(template.FuncMap(sprig.FuncMap())). - Parse(string(inFileData))) - buf := new(bytes.Buffer) - err = t.ExecuteTemplate(buf, "gen", vars) - checkerr(err) - - if filepath.Ext(outFile) == ".go" { - inFileData, err = format.Source(buf.Bytes()) - checkerr(err) - } else if filepath.Ext(outFile) == ".html" { - inFileData = gohtml.FormatBytes(buf.Bytes()) - } else { - inFileData = buf.Bytes() - } - - // don't overwrite existing files - if _, err := os.Stat(outFile); err == nil { - fmt.Printf("file already exists: %s, skipping...\n", outFile) - return - } - - err = os.WriteFile(outFile, inFileData, 0644) - checkerr(err) - buf.Reset() -} - -func checkerr(err error) { - if err != nil { - panic(err) - } -} diff --git a/cli/gen/routes_assets/layout.html.str b/cli/gen/routes_assets/layout.html.str deleted file mode 100644 index 9a0bdf0..0000000 --- a/cli/gen/routes_assets/layout.html.str +++ /dev/null @@ -1,23 +0,0 @@ - - - - - {{ fir.Name }} - - - - - - - - - - {{ template "content" . }} - - diff --git a/cli/gen/routes_assets/route.go.str b/cli/gen/routes_assets/route.go.str deleted file mode 100644 index adbadb4..0000000 --- a/cli/gen/routes_assets/route.go.str +++ /dev/null @@ -1,15 +0,0 @@ -package routes - -import ( - "github.com/livefir/fir" -) - -func [[.route]]() fir.RouteOptions { - return fir.RouteOptions{ - fir.Content("./routes/[[.routeLower]].html"), - fir.Layout("./routes/layout.html"), - fir.OnLoad(func(ctx fir.RouteContext) error { - return ctx.Data(map[string]any{"title": "[[.route]]"}) - }), - } -} diff --git a/cli/gen/routes_assets/route.html.str b/cli/gen/routes_assets/route.html.str deleted file mode 100644 index ceeeddb..0000000 --- a/cli/gen/routes_assets/route.html.str +++ /dev/null @@ -1,8 +0,0 @@ -{{ define "content" }} -
-

- {{ fir.Error "onload" }} -

-

{{ .title }} page

-
-{{ end }} diff --git a/cli/gen/simple_assets/app.html.str b/cli/gen/simple_assets/app.html.str deleted file mode 100644 index 3c458f6..0000000 --- a/cli/gen/simple_assets/app.html.str +++ /dev/null @@ -1,31 +0,0 @@ - - - - - - - - - -
-
- {{ block "count" . }} -
- Count: - {{ .count }} -
- {{ end }} -
-
- - -
-
- - diff --git a/cli/gen/simple_assets/main.go.str b/cli/gen/simple_assets/main.go.str deleted file mode 100644 index 71cf5bd..0000000 --- a/cli/gen/simple_assets/main.go.str +++ /dev/null @@ -1,31 +0,0 @@ -package main - -import ( - "net/http" - "sync/atomic" - - "github.com/livefir/fir" -) - -func index() fir.RouteOptions { - var count int32 - return fir.RouteOptions{ - fir.ID("[[.projectName]]"), - fir.Content("app.html"), - fir.OnLoad(func(ctx fir.RouteContext) error { - return ctx.KV("count", atomic.LoadInt32(&count)) - }), - fir.OnEvent("inc", func(ctx fir.RouteContext) error { - return ctx.KV("count", atomic.AddInt32(&count, 1)) - }), - fir.OnEvent("dec", func(ctx fir.RouteContext) error { - return ctx.KV("count", atomic.AddInt32(&count, -1)) - }), - } -} - -func main() { - controller := fir.NewController("[[.projectName]]", fir.DevelopmentMode(true)) - http.Handle("/", controller.RouteFunc(index)) - http.ListenAndServe(":9867", nil) -} diff --git a/cli/main.go b/cli/main.go deleted file mode 100644 index 4a604df..0000000 --- a/cli/main.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright © 2022 Adnaan Badr badr.adnaan@gmail.com - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -*/ -package main - -import ( - "github.com/livefir/fir/cli/cmd" -) - -func main() { - cmd.Execute() -}