diff --git a/README.md b/README.md index 6db2bc4..4d54838 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Go Bootstrapper +# BootstrapCLI -**Go Bootstrapper** is a CLI tool that scaffolds production-ready Golang projects β€” no dependency headaches, no manual setup. +**BootstrapCLI** is a CLI tool that scaffolds production-ready Golang projects β€” no dependency headaches, no manual setup. Just run a command and get a fully configured project with linters, routers, and structure ready to code. * * * @@ -18,74 +18,106 @@ Once installed, confirm the installation: ## Quick Start πŸ’¨ -Create a REST API project using **Gin**: +#### 1. Create a New Project ``` -bootstrap new myapp --type=rest --router=gin --port=8080 +bootstrap new myapp --type=rest --router=gin --port=8080 --db=postgres ``` +- This command scaffolds a production-ready Go project with: +- Standard project structure +- Database configuration +- Router setup +- Makefile and tooling -Create a project with **PostgreSQL** integration: +#### 2. Prepare the Project ``` -bootstrap new myapp --type=rest --router=gin --db=postgres +cd myapp && make tidy +``` + +#### 3. Start Required Services (Database) +``` +docker compose up -d +``` + +Before running ``make run`` make sure that you have running 'db' in docker, running with the same credentials as in .env file. + +#### 4. Run the Application + +``` +make run ``` -* * * ## Example Project Structure ``` myapp/ -β”œβ”€β”€ Makefile -β”œβ”€β”€ README.md -β”œβ”€β”€ cmd/ -β”‚ └── main.go -β”œβ”€β”€ internal/ -β”‚ β”œβ”€β”€ config/ -β”‚ β”‚ └── config.go -β”‚ β”œβ”€β”€ handler/ -β”‚ β”‚ └── user_handler.go -β”‚ β”œβ”€β”€ router/ -β”‚ β”‚ └── routes.go -β”‚ └── db/ ← created only if --db flag is passed -β”‚ └── db.go -└── go.mod + β”œβ”€β”€ cmd + β”‚ └── main.go + β”œβ”€β”€ docker-compose.yml + β”œβ”€β”€ go.mod + β”œβ”€β”€ go.sum + β”œβ”€β”€ internal + β”‚ β”œβ”€β”€ config + β”‚ β”‚ β”œβ”€β”€ config.go + β”‚ β”‚ └── config_test.go + β”‚ β”œβ”€β”€ db + β”‚ β”‚ └── database.go + β”‚ β”œβ”€β”€ handler + β”‚ β”‚ └── user_handler.go + β”‚ β”œβ”€β”€ model + β”‚ β”‚ β”œβ”€β”€ registory.go + β”‚ β”‚ └── user_model.go + β”‚ β”œβ”€β”€ repository + β”‚ β”‚ └── user_repo.go + β”‚ β”œβ”€β”€ server + β”‚ β”‚ β”œβ”€β”€ routes.go + β”‚ β”‚ └── server.go + β”‚ └── service + β”‚ └── user_service.go + β”œβ”€β”€ Makefile + β”œβ”€β”€ project.yaml + └── README.md ``` -* * * - ## CLI Options +### `new` -| Flag | Description | Example | -| --- | --- | --- | -| --type | Type of project (rest, grpc, etc.) | --type=rest | -| --router | Router framework (gin, chi, echo) | --router=gin | -| --port | Application port | --port=8080 | -| --db | Database integration | --db=postgres | +Creates a new project with the specified configuration options. -* * * +### Flags -## Why Go Bootstrapper? +| Flag | Description | Example | +|--------------|-------------------------------------------------|----------------------| +| `--type` | Type of project (e.g., `rest`) | `--type=rest` | +| `--router` | Router framework (`gin`, `chi`, `echo`, `fiber`) | `--router=gin` | +| `--port` | Application port | `--port=8080` | +| `--db` | Database integration | `--db=postgres` | +| `--entities` | Add entities | `--entities=user` | -Developers often waste time repeating setup tasks β€” creating folders, configuring routers, writing Makefiles, adding linters, etc. -**Go Bootstrapper** automates all that. -You focus on business logic β€” it handles the rest. +### `apply` +Create a new project using yaml file configurations +| Flag | Description | Example | +|--------------|------------------------------------------------- |----------------------| +| `--yaml` | unique file name for the yaml file | `--yaml=project.yaml`| -It’s like: +**BootstrapCLI** automates all that. +You focus on business logic β€” it handles the rest. -> `create-react-app`, but for Golang οΏ½ +> Note: This is my first OSS project, I want to make a CLI tool(maybe webUI) which is not just generator tool which only generate +> go code, but it will help developers to follow best practices, and assist during the project development. In future versions of the project i will add AI which will help developer to assist during their development and help in debugging + fixing error. I am adding AI not to generate code in there project but for assisting purpose only. * * * ## Roadmap -* Add `--with-auth` flag for JWT + middleware setup -* `add` command to make CLI tool more extensible to generate ``service``, ``handlers``, ``controllers``. -* Commands like ``build``, ``test``, ``dev``, ``fmt`` to make it more developer friendly, ensuring production ready code. -* ``init`` that will be used for letting users to choose their configurations via ``TUI``. - +* Add CLI command that let users to write their project description, to generate the project automatically without using flags. +* Command such as ``explain``, ``error`` , ``upgrade`` for the tool to make it progressive CLI tool. +* Add support for ``auth``, ``logging`` , ``observability`` and so on if it make sense. +* Add functionality in which users can switch to other options, for example postgres -> mongodb. * * * @@ -94,12 +126,12 @@ It’s like: Contributions, feedback, and ideas are welcome! Feel free to open an issue or PR on [GitHub](https://github.com/upsaurav12/bootstrap). -Consider star the project πŸ™ +Hope you like this project. * * * ## License -Licensed under the **MIT License** Β© 2025 [Saurav Upadhyay](https://github.com/upsaurav12) +Licensed under the **MIT License** Β© 2026 [Saurav Upadhyay](https://github.com/upsaurav12) * * * diff --git a/cmd/new.go b/cmd/new.go index 9384f00..6f10936 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -142,6 +142,7 @@ type TemplateData struct { OtherImports string UpperEntity []string ApiGroup func(entity string, get string, lowerentity string) string + IsAPIGroup bool Get string FullContext string ToTheClient string @@ -215,6 +216,7 @@ func buildTemplateData(projectName string, Returnable: frameworkConfig.Returnable, ReturnKeyword: frameworkConfig.ReturnKeyword, HTTPHandler: frameworkConfig.HTTPHandler, + IsAPIGroup: frameworkConfig.IsAPIGroup, Entities: Entities, // UpperEntity: , } @@ -246,6 +248,7 @@ func buildTemplateData(projectName string, ReturnKeyword: frameworkConfig.ReturnKeyword, HTTPHandler: frameworkConfig.HTTPHandler, Entities: yamlConfig.Entities, + IsAPIGroup: frameworkConfig.IsAPIGroup, } } diff --git a/pkg/framework/framework.go b/pkg/framework/framework.go index 12bc90b..011ba89 100644 --- a/pkg/framework/framework.go +++ b/pkg/framework/framework.go @@ -24,6 +24,7 @@ type FrameworkConfig struct { ReturnKeyword string HTTPHandler string Entities []string + IsAPIGroup bool } var FrameworkRegistory = map[string]FrameworkConfig{ @@ -38,6 +39,7 @@ var FrameworkRegistory = map[string]FrameworkConfig{ Start: "gin.Default()", OtherImports: `"net/http"`, FullContext: "c *gin.Context", + IsAPIGroup: true, ApiGroup: func(entity string, get string, lowerentity string) string { apiGroup := fmt.Sprintf(` { @@ -80,18 +82,19 @@ var FrameworkRegistory = map[string]FrameworkConfig{ "github.com/go-chi/render" "net/http" `, + IsAPIGroup: false, ApiGroup: func(entity string, get string, lowerentity string) string { apiGroup := fmt.Sprintf(` r.Group(func(r chi.Router) { - r.%s("/%s", handler.Get%ss) + r.%s("/%s", %sHandler.Get%ss) }) - `, get, lowerentity, entity) + `, get, lowerentity, lowerentity, entity) return apiGroup }, Get: "Get", FullContext: "w http.ResponseWriter, r *http.Request", - ToTheClient: "json.NewEncoder(w).Encode(", + ToTheClient: "render.JSON(w,r,", Response: "(w, r,", ImportRouter: ` "encoding/json" @@ -117,17 +120,16 @@ var FrameworkRegistory = map[string]FrameworkConfig{ Router: "*echo.Echo", Start: "echo.New()", OtherImports: `"net/http"`, - + IsAPIGroup: true, ApiGroup: func(entity, get, lowerentity string) string { return fmt.Sprintf(` - api := r.Group("/api/v1") { %s := api.Group("/%s") { - %s.%s("", handler.Get%ss) + %s.%s("", %sHandler.Get%ss) } } - `, lowerentity, lowerentity, lowerentity, get, entity) + `, lowerentity, lowerentity, lowerentity, get, lowerentity, entity) }, Get: "GET", @@ -162,17 +164,17 @@ var FrameworkRegistory = map[string]FrameworkConfig{ Router: "*fiber.App", Start: "fiber.New()", OtherImports: `"net/http"`, - + IsAPIGroup: true, ApiGroup: func(entity, get, lowerentity string) string { return fmt.Sprintf(` api := r.Group("/api/v1") { %s := api.Group("/%s") { - %s.%s("", handler.Get%ss) + %s.%s("", %sHandler.Get%ss) } } - `, lowerentity, lowerentity, lowerentity, get, entity) + `, lowerentity, lowerentity, lowerentity, get, lowerentity, entity) }, Get: "Get", diff --git a/project.yaml b/project.yaml index e8e4e27..06e453d 100644 --- a/project.yaml +++ b/project.yaml @@ -2,9 +2,9 @@ project: name: "test1" port: 8080 arch: "clean" - router: "chi" # or gin / echo / fiber + router: "chi" + db: "postgres" entities: - user - product -- payment diff --git a/templates/rest/clean/internal/handler/example_handler.go.tmpl b/templates/rest/clean/internal/handler/example_handler.go.tmpl index 71f31dc..7f70d14 100644 --- a/templates/rest/clean/internal/handler/example_handler.go.tmpl +++ b/templates/rest/clean/internal/handler/example_handler.go.tmpl @@ -2,9 +2,8 @@ package handler import ( "{{.ModuleName}}/internal/service" - "net/http" - "github.com/gin-gonic/gin" + {{.ImportHandler}} ) type {{.Entity}}Handler struct { @@ -15,7 +14,7 @@ func New{{.Entity}}Handler(s *service.{{.Entity}}Service) *{{.Entity}}Handler { return &{{.Entity}}Handler{Service: s} } -func (h *{{.Entity}}Handler) Get{{.Entity}}s(c *gin.Context) { +func (h *{{.Entity}}Handler) Get{{.Entity}}s({{.FullContext}}) {{.Returnable}}{ {{.LowerEntity}}s, _ := h.Service.Get{{.Entity}}s() - c.JSON(http.StatusOK, {{.LowerEntity}}s) + {{.ReturnKeyword}} {{.ToTheClient}} {{.LowerEntity}}s) } diff --git a/templates/rest/clean/internal/server/routes.go.tmpl b/templates/rest/clean/internal/server/routes.go.tmpl index 7083f8e..2074394 100644 --- a/templates/rest/clean/internal/server/routes.go.tmpl +++ b/templates/rest/clean/internal/server/routes.go.tmpl @@ -16,8 +16,9 @@ func (s *Server) RegisterRoutes() {{.HTTPHandler}} { gormDB := s.db.GetDB() - + {{- if .IsAPIGroup }} api := r.Group("/api/v1") + {{- end }} {{ if .Entities }} {{ range $i, $entity := .Entities }}