diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 64f0190..5e3b2d4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,4 +22,4 @@ jobs: run: go mod tidy - name: Run tests - run: go test ./... \ No newline at end of file + run: go test -v ./... \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e69de29 diff --git a/cmd/new.go b/cmd/new.go index 91f6187..4af1e67 100644 --- a/cmd/new.go +++ b/cmd/new.go @@ -1,6 +1,6 @@ /* -Copyright © 2025 Saurav Upadhyay sauravup041103@gmail.com +Copyright © 2025 NAME HERE */ @@ -10,378 +10,33 @@ import ( "fmt" "io" "io/fs" - "log" "os" "path/filepath" - "strconv" "strings" "text/template" - "unicode" "github.com/spf13/cobra" - "github.com/upsaurav12/bootstrap/pkg/addons" - "github.com/upsaurav12/bootstrap/pkg/framework" - "github.com/upsaurav12/bootstrap/pkg/parser" "github.com/upsaurav12/bootstrap/templates" - - "github.com/charmbracelet/bubbles/list" - "github.com/charmbracelet/bubbles/textinput" - tea "github.com/charmbracelet/bubbletea" - "github.com/charmbracelet/lipgloss" - "github.com/common-nighthawk/go-figure" -) - -type ProjectInput struct { - Name string - Type string - Router string - Port string - DB string - Entities []string -} - -var asciiStyle = lipgloss.NewStyle(). - Foreground(lipgloss.Color(primaryBlue)). - Bold(true) - -const ( - stepName = iota - stepType - stepRouter - stepPort - stepDB - stepConfirm ) -var ( - titleStyle = lipgloss.NewStyle(). - Bold(true). - Foreground(lipgloss.Color(softBlue)) - - labelStyle = lipgloss.NewStyle(). - Foreground(lipgloss.Color(softBlue)) - - hintStyle = lipgloss.NewStyle(). - Foreground(lipgloss.Color(mutedGray)) - - boxStyle = lipgloss.NewStyle(). - Padding(3, 2). - Border(lipgloss.RoundedBorder()). - BorderForeground(borderGray). - Width(60) -) - -func renderStep(m wizardModel, title, label, body, hint string) string { - content := lipgloss.JoinVertical( - lipgloss.Left, - titleStyle.Render(title), - "", - labelStyle.Render(label), - "", - body, - "", - hintStyle.Render(hint), - ) - - box := boxStyle. - Width(m.width - 4). - Height(m.height - 2). - Render(content) - - return box -} - -type wizardModel struct { - step int - input ProjectInput - - text textinput.Model - list list.Model - quit bool - - width int - height int -} - -type item string - -func (i item) Title() string { return string(i) } -func (i item) Description() string { return "" } -func (i item) FilterValue() string { return string(i) } - -func initialWizardModel() wizardModel { - return wizardModel{ - step: stepName, - text: newTextInput(""), - } -} - -const ( - primaryBlue = lipgloss.Color("33") // bright blue - softBlue = lipgloss.Color("39") // lighter blue - mutedGray = lipgloss.Color("241") // hints - borderGray = lipgloss.Color("238") // borders -) - -func newTextInput(placeholder string) textinput.Model { - ti := textinput.New() - ti.Prompt = "› " - ti.Placeholder = placeholder - ti.SetValue("") // ← critical - ti.Focus() - return ti -} - -func (m wizardModel) Init() tea.Cmd { - return nil -} - -func renderHeader() string { - fig := figure.NewFigure("Bootstrap CLI", "slant", true) - - ascii := strings.Trim(fig.String(), "\n") - - return asciiStyle.Render(ascii) -} - -func (m wizardModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) { - - switch msg := msg.(type) { - - // ✅ HANDLE WINDOW SIZE FIRST - case tea.WindowSizeMsg: - m.width = msg.Width - m.height = msg.Height - return m, nil - - // ✅ HANDLE KEYS - case tea.KeyMsg: - switch msg.String() { - - case "ctrl+c", "esc": - m.quit = true - return m, tea.Quit - - case "enter": - switch m.step { - - case stepName: - m.input.Name = m.text.Value() - m.step = stepType - m.list = newList("Project type", []string{"rest"}) - return m, nil - - case stepType: - m.input.Type = m.list.SelectedItem().(item).Title() - m.step = stepRouter - m.list = newList("Router", []string{"gin", "chi", "echo"}) - return m, nil - - case stepRouter: - m.input.Router = m.list.SelectedItem().(item).Title() - m.step = stepPort - m.text = newTextInput("") - return m, nil - - case stepPort: - port := m.text.Value() - if port == "" { - port = "8080" - } - if _, err := strconv.Atoi(port); err != nil { - return m, nil - } - m.input.Port = port - m.step = stepDB - m.list = newList("Database", []string{"postgres", "mysql", "mongo"}) - return m, nil - - case stepDB: - m.input.DB = m.list.SelectedItem().(item).Title() - m.step = stepConfirm - return m, nil - - case stepConfirm: - return m, tea.Quit - } - } - } - - var cmd tea.Cmd - if m.step == stepName || m.step == stepPort { - m.text, cmd = m.text.Update(msg) - return m, cmd - } - - if m.step == stepType || m.step == stepRouter || m.step == stepDB { - m.list, cmd = m.list.Update(msg) - return m, cmd - } - - return m, nil -} - -func (m wizardModel) View() string { - if m.quit { - return "" - } - - switch m.step { - - case stepName: - return renderStep( - m, - renderHeader()+"\nCreate New Project", - "Project name", - m.text.View(), - "Enter to continue • Esc to quit", - ) - - case stepType: - return renderStep( - m, - "Project Type", - "Select project type", - m.list.View(), - "↑↓ navigate • Enter select • Esc quit", - ) - - case stepRouter: - return renderStep( - m, - "Router", - "Select router", - m.list.View(), - "↑↓ navigate • Enter select • Esc quit", - ) - - case stepPort: - return renderStep( - m, - "Application Port", - "Port (default: 8080)", - m.text.View(), - "Enter to continue • Esc quit", - ) - - case stepDB: - return renderStep( - m, - "Database", - "Select database", - m.list.View(), - "↑↓ navigate • Enter select • Esc quit", - ) - - case stepConfirm: - summary := fmt.Sprintf( - "Project: %s\nType: %s\nRouter: %s\nPort: %s\nDatabase: %s", - m.input.Name, - m.input.Type, - m.input.Router, - m.input.Port, - m.input.DB, - ) - - return renderStep( - m, - "Confirm Configuration", - "Review your selections", - summary, - "Enter to generate • Esc to cancel", - ) - } - - return "" -} - -func newList(title string, values []string) list.Model { - items := make([]list.Item, len(values)) - for i, v := range values { - items[i] = item(v) - } - - l := list.New(items, list.NewDefaultDelegate(), 20, 10) - l.Title = title - return l -} - -func copyProjectYAML(srcPath, destDir string) error { - if srcPath == "" { - return nil // nothing to copy - } - - content, err := os.ReadFile(srcPath) - if err != nil { - return err - } - - destPath := filepath.Join(destDir, "project.yaml") - - return os.WriteFile(destPath, content, 0644) -} - -func RunInteractiveWizard() (*ProjectInput, error) { - p := tea.NewProgram(initialWizardModel()) - model, err := p.Run() - if err != nil { - return nil, err - } - - m := model.(wizardModel) - if m.quit { - return nil, fmt.Errorf("aborted") - } - - return &m.input, nil -} - // newCmd represents the new command var newCmd = &cobra.Command{ Use: "new", Short: "command for creating a new project.", Long: `command for creating a new project.`, Run: func(cmd *cobra.Command, args []string) { - interactive, _ := cmd.Flags().GetBool("interactive") - - if interactive || (len(args) == 0 && YAMLPath == "") { - input, err := RunInteractiveWizard() - if err != nil { - fmt.Fprintln(cmd.OutOrStdout(), err) - return - } - - projectType = input.Type - projectRouter = input.Router - projectPort = input.Port - DBType = input.DB - Entities = input.Entities - - createNewProject(input.Name, input.Router, input.Type, cmd.OutOrStdout()) - return - } - - var dirName string - if len(args) < 1 && YAMLPath != "" { - yamlConfig, err := parser.ReadYAML(YAMLPath) - if err != nil { - fmt.Println("error while creating project using yaml: ", err) - return - } - - dirName = yamlConfig.Project.Name - } else { - dirName = args[0] - } - // Check if the project name is provided - if len(args) < 1 && YAMLPath == "" { + if len(args) < 1 { fmt.Fprintln(cmd.OutOrStdout(), "Error: project name is required") return } + // Get the template flag value from the command context tmpl, _ := cmd.Flags().GetString("type") + // Get the project name (first argument) + dirName := args[0] + // Create the new project createNewProject(dirName, projectRouter, tmpl, cmd.OutOrStdout()) }, @@ -391,55 +46,6 @@ var projectType string var projectPort string var projectRouter string var DBType string -var YAMLPath string -var Entitys string -var Entities []string -var yamlFile string - -type TemplateData struct { - Name string - ModuleName string - PortName string - DBType string - Imports string - Start string - Entity string - Entities []string - ContextName string - ContextType string - Router string - Bind string - JSON string - LowerEntity string - OtherImports string - UpperEntity []string - ApiGroup func(entity string, get string, lowerentity string) string - Get string - FullContext string - ToTheClient string - Response string - ImportHandler string - ImportRouter string - ServiceName string - Image string - Environment string - Port string - Volume string - VolumeName string - DBName string - DBEnvPrefix string - Import string - Driver string - DSN string - Returnable string - ReturnKeyword string - HTTPHandler string -} - -type TemplateJob struct { - TemplateDir string - DestDir string -} func init() { // Add the new command to the rootCmd @@ -450,216 +56,56 @@ func init() { newCmd.Flags().StringVar(&projectPort, "port", "", "port of the project") newCmd.Flags().StringVar(&projectRouter, "router", "", "router of the project") newCmd.Flags().StringVar(&DBType, "db", "", "data type of the project") - newCmd.Flags().StringVar(&YAMLPath, "yaml", "", "yaml file path") - newCmd.Flags().StringVar(&Entitys, "entity", "", "entity") - newCmd.Flags().StringSliceVar(&Entities, "entities", nil, "different entities") - newCmd.Flags().Bool("interactive", false, "run interactive project setup") - -} - -func buildTemplateData(projectName string, - projectPort string, - frameworkConfig framework.FrameworkConfig, - dbConfig *addons.DbAddOneConfig, // optional - yamlConfig *parser.Config, uppercase []string) TemplateData { - - data := TemplateData{ - Name: frameworkConfig.Name, - ModuleName: projectName, - PortName: projectPort, - DBType: DBType, - Imports: frameworkConfig.Imports, - Start: frameworkConfig.Start, - ContextName: frameworkConfig.ContextName, - ContextType: frameworkConfig.ContextType, - Router: frameworkConfig.Router, - Bind: frameworkConfig.Bind, - JSON: frameworkConfig.JSON, - LowerEntity: Entitys, - OtherImports: frameworkConfig.OtherImports, - ApiGroup: frameworkConfig.ApiGroup, - Get: frameworkConfig.Get, - FullContext: frameworkConfig.FullContext, - ToTheClient: frameworkConfig.ToTheClient, - Response: frameworkConfig.Response, - ImportHandler: frameworkConfig.ImportHandler, - ImportRouter: frameworkConfig.ImportRouter, - Returnable: frameworkConfig.Returnable, - ReturnKeyword: frameworkConfig.ReturnKeyword, - HTTPHandler: frameworkConfig.HTTPHandler, - Entities: Entities, - // UpperEntity: , - } - - if yamlConfig != nil { - data = TemplateData{ - Name: frameworkConfig.Name, - ModuleName: projectName, - PortName: projectPort, - DBType: yamlConfig.Project.Database, - Imports: frameworkConfig.Imports, - Start: frameworkConfig.Start, - ContextName: frameworkConfig.ContextName, - ContextType: frameworkConfig.ContextType, - Router: frameworkConfig.Router, - Bind: frameworkConfig.Bind, - JSON: frameworkConfig.JSON, - LowerEntity: Entitys, - UpperEntity: nil, - OtherImports: frameworkConfig.OtherImports, - ApiGroup: frameworkConfig.ApiGroup, - Get: frameworkConfig.Get, - FullContext: frameworkConfig.FullContext, - ToTheClient: frameworkConfig.ToTheClient, - Response: frameworkConfig.Response, - ImportHandler: frameworkConfig.ImportHandler, - ImportRouter: frameworkConfig.ImportRouter, - Returnable: frameworkConfig.Returnable, - ReturnKeyword: frameworkConfig.ReturnKeyword, - HTTPHandler: frameworkConfig.HTTPHandler, - Entities: yamlConfig.Entities, - } - } - - if dbConfig != nil { - data.ServiceName = dbConfig.ServiceName - data.DBName = dbConfig.DBName - data.DBEnvPrefix = dbConfig.DBEnvPrefix - data.Port = dbConfig.Port - data.DSN = dbConfig.DSN - data.Driver = dbConfig.Driver - data.Import = dbConfig.Import - data.Image = dbConfig.Image - data.Environment = dbConfig.Environment - data.Volume = dbConfig.Volume - data.VolumeName = dbConfig.VolumeName - } - - return data } -func returnUppercase(entity string) string { - if entity == "" { - return "" - } - - runes := []rune(entity) - runes[0] = unicode.ToUpper(runes[0]) - - return string(runes) -} - -func createNewProject(projectName, projectRouter, template string, out io.Writer) { +func createNewProject(projectName string, projectRouter string, template string, out io.Writer) { err := os.Mkdir(projectName, 0755) if err != nil { - log.Fatalf("error occured while creating a new project %s: ", err) - } - err = os.MkdirAll(filepath.Join(projectName, "internal"), 0755) - - if err != nil { - log.Fatalf("error occured while creating a new project %s: ", projectName) - } - - // ✅ COPY project.yaml if provided - if err := copyProjectYAML(YAMLPath, projectName); err != nil { - fmt.Fprintf(out, "warning: could not copy project.yaml: %v\n", err) - } - - // Prepare configs - - var frameworkConfig framework.FrameworkConfig - frameworkConfig = framework.FrameworkRegistory[projectRouter] - - var dbConfig *addons.DbAddOneConfig - - jobs := []TemplateJob{ - {"common", projectName}, - {"rest/clean", projectName}, - } - - var data TemplateData - - var yamlConfig *parser.Config - - if YAMLPath != "" { - var err error - yamlConfig, err = parser.ReadYAML(YAMLPath) - if err != nil { - fmt.Printf("error while reading yaml file: %s", err) - return - } - } - - if DBType != "" { - cfg := addons.DbRegistory[DBType] - dbConfig = &cfg - } - if DBType == "" && yamlConfig != nil { - DBType = yamlConfig.Project.Database - cfg := addons.DbRegistory[DBType] - dbConfig = &cfg - } - - if yamlConfig != nil { - - frameworkConfig = framework.FrameworkRegistory[yamlConfig.Project.Router] - Entities = yamlConfig.Entities - - if yamlConfig.Project.Database != "" { - - cfg := addons.DbRegistory[yamlConfig.Project.Database] - dbConfig = &cfg - - DBType = yamlConfig.Project.Database - - } + fmt.Fprintf(out, "Error creating directory: %v\n", err) + return } + // Print the template that was passed - var uppercase []string + // Always add README + Makefile from common + renderTemplateDir("common", projectName, TemplateData{ + ModuleName: projectName, + PortName: projectPort, + }) - for _, entity := range Entities { - u := returnUppercase(entity) + renderTemplateDir("rest"+"/"+projectRouter, projectName, TemplateData{ + ModuleName: projectName, + PortName: projectPort, + DBType: DBType, + }) - uppercase = append(uppercase, u) + if err != nil { + fmt.Fprintf(out, "Error rendering templates: %v\n", err) + return } - data = buildTemplateData( - projectName, - projectPort, - frameworkConfig, - dbConfig, - yamlConfig, uppercase) - - data.UpperEntity = uppercase - - // Render templates - _ = renderTemplateDir("common", projectName, data) - _ = renderTemplateDir("rest/clean", projectName, data) - if DBType != "" { - jobs = append(jobs, - TemplateJob{"db/" + DBType, projectName}, - TemplateJob{"db/database", filepath.Join(projectName, "internal", "db")}, - ) - - // fmt.Fprintf(out, "✓ Added database support for '%s'\n", DBType) - } + dbTemplatePath := "db/" + DBType + err := renderTemplateDir(dbTemplatePath, filepath.Join(projectName, "internal", "db"), TemplateData{ + ModuleName: projectName, + PortName: projectPort, + DBType: DBType, + }) + if err != nil { - for _, job := range jobs { - if err := renderTemplateDir(job.TemplateDir, job.DestDir, data); err != nil { - fmt.Fprintf(out, "Error rendering template %s → %s: %v\n", - job.TemplateDir, job.DestDir, err) + fmt.Fprintf(out, "Error rendering DB templates: %v\n", err) return } + + fmt.Fprintf(out, "✓ Added database support for '%s'\n", DBType) } fmt.Fprintf(out, "✓ Created '%s' successfully\n", projectName) } -func IsHidden(path string) (bool, error) { - // Unix hidden check - name := filepath.Base(path) - return strings.HasPrefix(name, "."), nil +type TemplateData struct { + ModuleName string + PortName string + DBType string } func renderTemplateDir(templatePath, destinationPath string, data TemplateData) error { @@ -668,76 +114,33 @@ func renderTemplateDir(templatePath, destinationPath string, data TemplateData) return err } + // Compute relative path (remove the base templatePath) relPath, _ := filepath.Rel(templatePath, path) + targetPath := filepath.Join(destinationPath, strings.TrimSuffix(relPath, ".tmpl")) if d.IsDir() { - return os.MkdirAll(filepath.Join(destinationPath, relPath), 0755) + return os.MkdirAll(targetPath, 0755) } + // ✅ Important: use full `path` for ReadFile content, err := templates.FS.ReadFile(path) if err != nil { return err } - fileName := strings.TrimSuffix(relPath, ".tmpl") - - if templatePath == "common" { - base := filepath.Base(fileName) - if base == "env" || base == "golang-ci.yml" { - fileName = "." + fileName - } - } - - if len(data.Entities) == 0 { - return writeSingle(data, fileName, path, content, destinationPath) + // Parse template + tmpl, err := template.New(filepath.Base(path)).Parse(string(content)) + if err != nil { + return err } - for _, entity := range data.Entities { - - // correct file renaming - newFile := strings.Replace( - fileName, - "example", - strings.ToLower(entity), - 1, // only first replacement - ) - - entityData := data - entityData.Entity = strings.Title(entity) - entityData.LowerEntity = strings.ToLower(entity) - // capture errors!! - if err := writeSingle(entityData, newFile, path, content, destinationPath); err != nil { - return err - } + // Write file + outFile, err := os.Create(targetPath) + if err != nil { + return err } + defer outFile.Close() - return nil + return tmpl.Execute(outFile, data) }) } - -func writeSingle(data TemplateData, fileName string, tmpltPath string, content []byte, destinationPath string) error { - newFile := strings.Replace( - fileName, - "example", - "user", - 1, // only first replacement - ) - - entityData := data - entityData.Entity = strings.Title("user") - entityData.LowerEntity = strings.ToLower("user") - targetPath := filepath.Join(destinationPath, newFile) - - tmpl, err := template.New(filepath.Base(tmpltPath)).Parse(string(content)) - if err != nil { - return err - } - - outFile, err := os.Create(targetPath) - if err != nil { - return err - } - defer outFile.Close() - - return tmpl.Execute(outFile, entityData) -} diff --git a/cmd/root.go b/cmd/root.go index f952a48..94bbfdf 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,5 +1,5 @@ /* -Copyright © 2025 Saurav Upadhyay sauravup041103@gmail.com +Copyright © 2025 NAME HERE */ package cmd diff --git a/go.mod b/go.mod index 1ec608b..2b5bc97 100644 --- a/go.mod +++ b/go.mod @@ -1,68 +1,13 @@ module github.com/upsaurav12/bootstrap -go 1.24.0 +go 1.23.6 require ( - github.com/gin-gonic/gin v1.11.0 - github.com/spf13/cobra v1.9.1 - github.com/stretchr/testify v1.11.1 - gopkg.in/yaml.v3 v3.0.1 -) - -require ( - github.com/atotto/clipboard v0.1.4 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/bytedance/sonic v1.14.0 // indirect - github.com/bytedance/sonic/loader v0.3.0 // indirect - github.com/charmbracelet/bubbles v0.21.0 // indirect - github.com/charmbracelet/bubbletea v1.3.10 // indirect - github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc // indirect - github.com/charmbracelet/lipgloss v1.1.0 // indirect - github.com/charmbracelet/x/ansi v0.10.1 // indirect - github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd // indirect - github.com/charmbracelet/x/term v0.2.1 // indirect - github.com/cloudwego/base64x v0.1.6 // indirect - github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect - github.com/gabriel-vasile/mimetype v1.4.8 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.27.0 // indirect - github.com/goccy/go-json v0.10.2 // indirect - github.com/goccy/go-yaml v1.18.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/lucasb-eyer/go-colorful v1.2.0 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect - github.com/mattn/go-runewidth v0.0.16 // indirect - github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect - github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/termenv v0.16.0 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/quic-go/qpack v0.5.1 // indirect - github.com/quic-go/quic-go v0.54.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/sahilm/fuzzy v0.1.1 // indirect + github.com/spf13/cobra v1.9.1 // indirect github.com/spf13/pflag v1.0.6 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.3.0 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - go.uber.org/mock v0.5.0 // indirect - golang.org/x/arch v0.20.0 // indirect - golang.org/x/crypto v0.40.0 // indirect - golang.org/x/mod v0.25.0 // indirect - golang.org/x/net v0.42.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.36.0 // indirect - golang.org/x/text v0.27.0 // indirect - golang.org/x/tools v0.34.0 // indirect - google.golang.org/protobuf v1.36.9 // indirect + github.com/stretchr/testify v1.10.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b7ced98..725c027 100644 --- a/go.sum +++ b/go.sum @@ -1,141 +1,17 @@ -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/bytedance/sonic v1.14.0 h1:/OfKt8HFw0kh2rj8N0F6C/qPGRESq0BbaNZgcNXXzQQ= -github.com/bytedance/sonic v1.14.0/go.mod h1:WoEbx8WTcFJfzCe0hbmyTGrfjt8PzNEBdxlNUO24NhA= -github.com/bytedance/sonic/loader v0.3.0 h1:dskwH8edlzNMctoruo8FPTJDF3vLtDT0sXZwvZJyqeA= -github.com/bytedance/sonic/loader v0.3.0/go.mod h1:N8A3vUdtUebEY2/VQC0MyhYeKUFosQU6FxH2JmUe6VI= -github.com/charmbracelet/bubbles v0.21.0 h1:9TdC97SdRVg/1aaXNVWfFH3nnLAwOXr8Fn6u6mfQdFs= -github.com/charmbracelet/bubbles v0.21.0/go.mod h1:HF+v6QUR4HkEpz62dx7ym2xc71/KBHg+zKwJtMw+qtg= -github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= -github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc h1:4pZI35227imm7yK2bGPcfpFEmuY1gc2YSTShr4iJBfs= -github.com/charmbracelet/colorprofile v0.2.3-0.20250311203215-f60798e515dc/go.mod h1:X4/0JoqgTIPSFcRA/P6INZzIuyqdFY5rm8tb41s9okk= -github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= -github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= -github.com/charmbracelet/x/ansi v0.10.1 h1:rL3Koar5XvX0pHGfovN03f5cxLbCF2YvLeyz7D2jVDQ= -github.com/charmbracelet/x/ansi v0.10.1/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= -github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd h1:vy0GVL4jeHEwG5YOXDmi86oYw2yuYUGqz6a8sLwg0X8= -github.com/charmbracelet/x/cellbuf v0.0.13-0.20250311204145-2c3ea96c31dd/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= -github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= -github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= -github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= -github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= -github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be h1:J5BL2kskAlV9ckgEsNQXscjIaLiOYiZ75d4e94E6dcQ= -github.com/common-nighthawk/go-figure v0.0.0-20210622060536-734e95fb86be/go.mod h1:mk5IQ+Y0ZeO87b858TlA645sVcEcbiX6YqP98kt+7+w= github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= -github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM= -github.com/gabriel-vasile/mimetype v1.4.8/go.mod h1:ByKUIKGjh1ODkGM1asKUbQZOLGrPjydw3hYPU2YU9t8= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.27.0 h1:w8+XrWVMhGkxOaaowyKH35gFydVHOvC0/uWoy2Fzwn4= -github.com/go-playground/validator/v10 v10.27.0/go.mod h1:I5QpIEbmr8On7W0TktmJAumgzX4CA1XNl4ZmDuVHKKo= -github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= -github.com/goccy/go-yaml v1.18.0 h1:8W7wMFS12Pcas7KU+VVkaiCng+kG8QiFeFwzFb+rwuw= -github.com/goccy/go-yaml v1.18.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= -github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= -github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= -github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= -github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= -github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI= -github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg= -github.com/quic-go/quic-go v0.54.0 h1:6s1YB9QotYI6Ospeiguknbp2Znb/jZYjZLRXn9kMQBg= -github.com/quic-go/quic-go v0.54.0/go.mod h1:e68ZEaCdyviluZmy44P6Iey98v/Wfz6HCjQEm+l8zTY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sahilm/fuzzy v0.1.1 h1:ceu5RHF8DGgoi+/dR5PsECjCDH1BE3Fnmpo7aVXOdRA= -github.com/sahilm/fuzzy v0.1.1/go.mod h1:VFvziUEIMCrT6A6tw2RFIXPXXmzXbOsSHF0DOI8ZK9Y= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.3.0 h1:Qd2W2sQawAfG8XSvzwhBeoGq71zXOC/Q1E9y/wUcsUA= -github.com/ugorji/go/codec v1.3.0/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU= -go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM= -golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c= -golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= -golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/main.go b/main.go index 6d9e210..18f6996 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,5 @@ /* -Copyright © 2025 Saurav Upadhyay sauravup041103@gmail.com +Copyright © 2025 NAME HERE */ package main diff --git a/pkg/addons/addon.go b/pkg/addons/addon.go deleted file mode 100644 index 1890561..0000000 --- a/pkg/addons/addon.go +++ /dev/null @@ -1 +0,0 @@ -package addons diff --git a/pkg/addons/dbAddOne.go b/pkg/addons/dbAddOne.go deleted file mode 100644 index 98247bd..0000000 --- a/pkg/addons/dbAddOne.go +++ /dev/null @@ -1,113 +0,0 @@ -package addons - -type DbAddOneConfig struct { - ServiceName string - Image string - Environment string - Port string - Volume string - VolumeName string - DBName string - DBEnvPrefix string - Import string - Driver string - DSN string - OutputFile string -} - -var DbRegistory = map[string]DbAddOneConfig{ - "postgres": { - ServiceName: "postgres_bp", - Image: "postgres:latest", - Environment: ` POSTGRES_DB: ${GONE_DB_DATABASE} - POSTGRES_USER: ${GONE_DB_USERNAME} - POSTGRES_PASSWORD: ${GONE_DB_PASSWORD}`, - Port: "5432", - Volume: "postgres_volume_bp:/var/lib/postgresql/data", - VolumeName: "postgres_volume_bp", - DBName: "PostgreSQL", - DBEnvPrefix: "BLUEPRINT", - Import: `_ "github.com/jackc/pgx/v5/stdlib"`, - Driver: "pgx", - DSN: "postgres://%s:%s@%s:%s/%s?sslmode=disable&search_path=%s", - }, - - "mysql": { - ServiceName: "mysql_bp", - Image: "mysql:8", - Environment: ` - MYSQL_DATABASE: ${GONE_DB_DATABASE} - MYSQL_USER: ${GONE_DB_USERNAME} - MYSQL_PASSWORD: ${GONE_DB_PASSWORD} - MYSQL_ROOT_PASSWORD: ${GONE_DB_PASSWORD}`, - Port: "3306", - Volume: "mysql_volume_bp:/var/lib/mysql", - VolumeName: "mysql_volume_bp", - DBName: "MySQL", - DBEnvPrefix: "BLUEPRINT", - Import: `_ "github.com/go-sql-driver/mysql"`, - Driver: "mysql", - DSN: "%s:%s@tcp(%s:%s)/%s", - OutputFile: "mysql.go", - }, - - "mongodb": { - ServiceName: "mongo_bp", - Image: "mongo:latest", - Environment: ` - MONGO_INITDB_DATABASE: ${GONE_DB_DATABASE} - MONGO_INITDB_ROOT_USERNAME: ${GONE_DB_USERNAME} - MONGO_INITDB_ROOT_PASSWORD: ${GONE_DB_PASSWORD}`, - Port: "27017", - Volume: "mongo_volume_bp:/data/db", - VolumeName: "mongo_volume_bp", - }, - - "sqlite": { - ServiceName: "sqlite_bp", - Image: "alpine:latest", - Environment: ` - # SQLite has no environment variables`, - Port: "0", // no port needed - Volume: "sqlite_volume_bp:/data", - VolumeName: "sqlite_volume_bp", - DBName: "SQLite", - DBEnvPrefix: "BLUEPRINT", - Import: `_ "modernc.org/sqlite"`, - Driver: "sqlite", - DSN: "file:%s.db?_pragma=journal_mode(WAL)", - }, - - "cockroachdb": { - ServiceName: "cockroach_bp", - Image: "cockroachdb/cockroach:latest", - Environment: ` - # CockroachDB has no env vars needed in insecure mode`, - Port: "26257", - Volume: "cockroach_volume_bp:/cockroach/cockroach-data", - VolumeName: "cockroach_volume_bp", - DBName: "CockroachDB", - DBEnvPrefix: "BLUEPRINT", - Import: `_ "github.com/jackc/pgx/v5/stdlib"`, - Driver: "pgx", - DSN: "postgres://%s:%s@%s:%s/%s?sslmode=disable", - }, - - "mariadb": { - ServiceName: "mariadb_bp", - Image: "mariadb:latest", - Environment: ` - MARIADB_DATABASE: ${GONE_DB_DATABASE} - MARIADB_USER: ${GONE_DB_USERNAME} - MARIADB_PASSWORD: ${GONE_DB_PASSWORD} - MARIADB_ROOT_PASSWORD: ${GONE_DB_PASSWORD}`, - Port: "3306", - Volume: "mariadb_volume_bp:/var/lib/mysql", - VolumeName: "mariadb_volume_bp", - DBName: "MariaDB", - DBEnvPrefix: "BLUEPRINT", - Import: `_ "github.com/go-sql-driver/mysql"`, - Driver: "mysql", - DSN: "%s:%s@tcp(%s:%s)/%s", - }, -} diff --git a/pkg/framework/framework.go b/pkg/framework/framework.go deleted file mode 100644 index 12bc90b..0000000 --- a/pkg/framework/framework.go +++ /dev/null @@ -1,213 +0,0 @@ -package framework - -import "fmt" - -type FrameworkConfig struct { - Name string - Imports string - Entity string - ContextName string - ContextType string - Bind string - JSON string - Router string - Start string - OtherImports string - ApiGroup func(entity string, get string, lowerentity string) string - Get string - FullContext string - ToTheClient string - Response string - ImportRouter string - ImportHandler string - Returnable string - ReturnKeyword string - HTTPHandler string - Entities []string -} - -var FrameworkRegistory = map[string]FrameworkConfig{ - "gin": { - Name: "gin", - Imports: `"github.com/gin-gonic/gin"`, - ContextName: "c", - ContextType: "*gin.Context", - Bind: "c.BindJSON", // func(obj any) error - JSON: "c.JSON", // func(code int, obj any) - Router: "*gin.Engine", - Start: "gin.Default()", - OtherImports: `"net/http"`, - FullContext: "c *gin.Context", - ApiGroup: func(entity string, get string, lowerentity string) string { - apiGroup := fmt.Sprintf(` - { - %s := api.Group("/%s") - { - %s.%s("", %sHandler.Get%ss) - } - } - `, lowerentity, lowerentity, lowerentity, get, lowerentity, entity) - - return apiGroup - }, - Get: "GET", - ToTheClient: "c.JSON(http.StatusOK, ", - Response: "(http.StatusOK,", - ImportRouter: ` - "net/http" - "github.com/gin-gonic/gin" - `, - ImportHandler: ` - "github.com/gin-gonic/gin" - "net/http" - `, - Returnable: "", - ReturnKeyword: "", - HTTPHandler: "http.Handler", - }, - - "chi": { - Name: "chi", - Imports: `"github.com/go-chi/chi/v5"`, - ContextName: "r", - ContextType: "http.ResponseWriter, *http.Request", // chi passes both - Bind: "json.NewDecoder(r.Body).Decode", // need encoding/json - JSON: "render.JSON", // from go-chi/render - Router: "chi.Router", - Start: "chi.NewRouter()", - OtherImports: ` - "encoding/json" - "github.com/go-chi/render" - "net/http" - `, - ApiGroup: func(entity string, get string, lowerentity string) string { - apiGroup := fmt.Sprintf(` - r.Group(func(r chi.Router) { - r.%s("/%s", handler.Get%ss) - }) - `, get, lowerentity, entity) - - return apiGroup - }, - Get: "Get", - FullContext: "w http.ResponseWriter, r *http.Request", - ToTheClient: "json.NewEncoder(w).Encode(", - Response: "(w, r,", - ImportRouter: ` - "encoding/json" - "net/http" - "github.com/go-chi/chi/v5" - `, - ImportHandler: ` - "net/http" - "github.com/go-chi/render" - `, - Returnable: "", - ReturnKeyword: "", - HTTPHandler: "http.Handler", - }, - - "echo": { - Name: "echo", - Imports: `"github.com/labstack/echo/v4"`, - ContextName: "c", - ContextType: "echo.Context", - Bind: "c.Bind", // func(obj interface{}) error - JSON: "c.JSON", // func(int, interface{}) error - Router: "*echo.Echo", - Start: "echo.New()", - OtherImports: `"net/http"`, - - ApiGroup: func(entity, get, lowerentity string) string { - return fmt.Sprintf(` - api := r.Group("/api/v1") - { - %s := api.Group("/%s") - { - %s.%s("", handler.Get%ss) - } - } - `, lowerentity, lowerentity, lowerentity, get, entity) - }, - - Get: "GET", - - FullContext: "c echo.Context", - - ToTheClient: "c.JSON(http.StatusOK, ", - - Response: "(http.StatusOK,", - - ImportRouter: ` - "net/http" - "github.com/labstack/echo/v4" - `, - - ImportHandler: ` - "net/http" - "github.com/labstack/echo/v4" - `, - Returnable: "error", - ReturnKeyword: "return", - HTTPHandler: "http.Handler", - }, - - "fiber": { - Name: "fiber", - Imports: `"github.com/gofiber/fiber/v2"`, - ContextName: "c", - ContextType: "*fiber.Ctx", - Bind: "c.BodyParser", // func(obj interface{}) error - JSON: "c.JSON", // func(obj interface{}) error - Router: "*fiber.App", - Start: "fiber.New()", - OtherImports: `"net/http"`, - - ApiGroup: func(entity, get, lowerentity string) string { - return fmt.Sprintf(` - api := r.Group("/api/v1") - { - %s := api.Group("/%s") - { - %s.%s("", handler.Get%ss) - } - } - `, lowerentity, lowerentity, lowerentity, get, entity) - }, - - Get: "Get", - - FullContext: "c *fiber.Ctx", - - ToTheClient: "c.JSON(", - - Response: "(fiber.StatusOK,", - - ImportRouter: ` - "github.com/gofiber/fiber/v2" - `, - - ImportHandler: ` - "github.com/gofiber/fiber/v2" - `, - - Returnable: "error", - ReturnKeyword: "return", - HTTPHandler: "*fiber.App", - }, - - "mux": { - Name: "mux", - Imports: `"github.com/gorilla/mux"`, - ContextName: "w, r", - ContextType: "http.ResponseWriter, *http.Request", - Bind: "json.NewDecoder(r.Body).Decode", - JSON: `json.NewEncoder(w).Encode`, - Router: "*mux.Router", - Start: "mux.NewRouter()", - OtherImports: ` - "encoding/json" - "net/http" - `, - }, -} diff --git a/pkg/parser/yamlParsing.go b/pkg/parser/yamlParsing.go deleted file mode 100644 index 7ea5126..0000000 --- a/pkg/parser/yamlParsing.go +++ /dev/null @@ -1,58 +0,0 @@ -package parser - -import ( - "fmt" - "os" - - "gopkg.in/yaml.v3" -) - -type Config struct { - Project Project `yaml:"project"` - // Feature Feature `yaml:"feature"` - Entities []string `yaml:"entities"` - CustomLogic []string `yaml:"custom_logic"` -} - -type Project struct { - Name string `yaml:"name"` - Type string `yaml:"type"` - Port int `yaml:"port"` - Location string `yaml:"location"` - Database string `yaml:"db"` - Router string `yaml:"router"` -} - -// type Feature struct { -// Database FeatureItem `yaml:"database"` -// Cache FeatureItem `yaml:"cache"` -// Queue FeatureItem `yaml:"queue"` -// Auth FeatureItem `yaml:"auth"` -// } - -type FeatureItem struct { - Name string `yaml:"name"` -} - -type ProjectYAML struct { - Name string `json:"name" yaml:"name"` - Layers []string `json:"layers" yaml:"layers"` - Features []string `json:"features" yaml:"features"` -} - -func ReadYAML(yamlPath string) (*Config, error) { - yamlByte, err := os.ReadFile(yamlPath) - if err != nil { - return &Config{}, err - } - - var yamlProject Config - - err = yaml.Unmarshal(yamlByte, &yamlProject) - if err != nil { - fmt.Println("error: ", err) - return &Config{}, err - } - - return &yamlProject, nil -} diff --git a/project.yaml b/project.yaml deleted file mode 100644 index e8e4e27..0000000 --- a/project.yaml +++ /dev/null @@ -1,10 +0,0 @@ -project: - name: "test1" - port: 8080 - arch: "clean" - router: "chi" # or gin / echo / fiber - -entities: -- user -- product -- payment diff --git a/templates/common/Makefile.tmpl b/templates/common/Makefile.tmpl index af53a03..2c7bea6 100644 --- a/templates/common/Makefile.tmpl +++ b/templates/common/Makefile.tmpl @@ -1,5 +1,5 @@ # Project variables -APP_NAME := {{.ModuleName}} +APP_NAME := {.ModuleName} BIN_DIR := bin MAIN_FILE := ./cmd/main.go PKG := ./... diff --git a/templates/common/env.tmpl b/templates/common/env.tmpl deleted file mode 100644 index 6163151..0000000 --- a/templates/common/env.tmpl +++ /dev/null @@ -1,8 +0,0 @@ -PORT={{.PortName}} -APP_ENV=local -GONE_DB_HOST=localhost -GONE_DB_PORT=5431 -GONE_DB_DATABASE=gone -GONE_DB_USERNAME=example_username -GONE_DB_PASSWORD=password1234 -GONE_DB_SCHEMA=public \ No newline at end of file diff --git a/templates/common/golang-ci.yml.tmpl b/templates/common/golang-ci.yml.tmpl deleted file mode 100644 index abd171c..0000000 --- a/templates/common/golang-ci.yml.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -run: - timeout: 5m - tests: true - -linters: - enable: - - govet - - errcheck - - staticcheck - - gofmt - - ineffassign - - unused diff --git a/templates/common/project.yaml.tmpl b/templates/common/project.yaml.tmpl deleted file mode 100644 index e75ab15..0000000 --- a/templates/common/project.yaml.tmpl +++ /dev/null @@ -1,14 +0,0 @@ -project: - name: "{{ .ModuleName }}" - port: {{ .Port }} - router: "{{ .Router }}" - database: "{{ .DBType }}" - -entities: -{{- if .Entities }} -{{- range .Entities }} - - {{ . }} -{{- end }} -{{- else }} - - user -{{- end }} diff --git a/templates/db/database/database.go.tmpl b/templates/db/database/database.go.tmpl deleted file mode 100644 index 259a580..0000000 --- a/templates/db/database/database.go.tmpl +++ /dev/null @@ -1,69 +0,0 @@ -package database - -import ( - "{{.ModuleName}}/internal/model" - "fmt" - "log" - "os" - - _ "github.com/jackc/pgx/v5/stdlib" - _ "github.com/joho/godotenv/autoload" - "gorm.io/driver/postgres" - "gorm.io/gorm" -) - -// Service represents a service that interacts with a database. -type Service interface { - Health() map[string]string - Close() error - GetDB() *gorm.DB -} - -type service struct { - db *gorm.DB -} - -var ( - database = os.Getenv("GONE_DB_DATABASE") - password = os.Getenv("GONE_DB_PASSWORD") - username = os.Getenv("GONE_DB_USERNAME") - port = os.Getenv("GONE_DB_PORT") - host = os.Getenv("GONE_DB_HOST") - schema = os.Getenv("GONE_DB_SCHEMA") - dbInstance *service -) - -func New() Service { - dsn := fmt.Sprintf( - "host=%s user=%s password=%s dbname=%s port=%s sslmode=disable", - host, username, password, database, port, - ) - - db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{}) - if err != nil { - log.Fatalf("failed to connect database: %v", err) - } - - db.AutoMigrate(model.Registry...) - - dbInstance = &service{db: db} - return dbInstance -} - -func (s *service) GetDB() *gorm.DB { - return s.db -} - -func (s *service) Health() map[string]string { - sqlDB, _ := s.db.DB() - err := sqlDB.Ping() - if err != nil { - return map[string]string{"status": "down"} - } - return map[string]string{"status": "up"} -} - -func (s *service) Close() error { - sqlDB, _ := s.db.DB() - return sqlDB.Close() -} diff --git a/templates/db/mongo/db.go.tmpl b/templates/db/mongo/db.go.tmpl new file mode 100644 index 0000000..ec2a96f --- /dev/null +++ b/templates/db/mongo/db.go.tmpl @@ -0,0 +1,34 @@ +package db + +import ( + "context" + "log" + "time" + + "go.mongodb.org/mongo-driver/mongo" + "go.mongodb.org/mongo-driver/mongo/options" +) + +var Client *mongo.Client + +func Connect() { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + + client, err := mongo.Connect(ctx, options.Client().ApplyURI("mongodb://localhost:27017")) + if err != nil { + log.Fatalf("✖ Failed to connect to MongoDB: %v", err) + } + + Client = client + log.Println("✓ Connected to MongoDB") +} + +func Close() { + if Client != nil { + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + Client.Disconnect(ctx) + log.Println("🔌 MongoDB connection closed") + } +} diff --git a/templates/db/mongo/docker-compose.yml.tmpl b/templates/db/mongo/docker-compose.yml.tmpl deleted file mode 100644 index e07d532..0000000 --- a/templates/db/mongo/docker-compose.yml.tmpl +++ /dev/null @@ -1,15 +0,0 @@ -services: - mongo_bp: - image: mongo:latest - restart: unless-stopped - environment: - MONGO_INITDB_DATABASE: ${GONE_DB_DATABASE} - MONGO_INITDB_ROOT_USERNAME: ${GONE_DB_USERNAME} - MONGO_INITDB_ROOT_PASSWORD: ${GONE_DB_PASSWORD} - ports: - - "${GONE_DB_PORT}:27017" - volumes: - - mongo_volume_bp:/data/db - -volumes: - mongo_volume_bp: \ No newline at end of file diff --git a/templates/db/mysql/db.go.tmpl b/templates/db/mysql/db.go.tmpl new file mode 100644 index 0000000..31260de --- /dev/null +++ b/templates/db/mysql/db.go.tmpl @@ -0,0 +1,27 @@ +package db + +import ( + "database/sql" + "log" + + _ "github.com/go-sql-driver/mysql" +) + +var DB *sql.DB + +func Connect() { + connStr := "user:password@tcp(localhost:3306)/app_db" + var err error + DB, err = sql.Open("mysql", connStr) + if err != nil { + log.Fatalf("✖ Failed to connect to MySQL: %v", err) + } + log.Println("✓ Connected to MySQL database") +} + +func Close() { + if DB != nil { + DB.Close() + log.Println("🔌 MySQL connection closed") + } +} diff --git a/templates/db/mysql/docker-compose.yml.tmpl b/templates/db/mysql/docker-compose.yml.tmpl deleted file mode 100644 index fee41d9..0000000 --- a/templates/db/mysql/docker-compose.yml.tmpl +++ /dev/null @@ -1,16 +0,0 @@ -services: - mysql_bp: - image: mysql:8 - restart: unless-stopped - environment: - MYSQL_DATABASE: ${GONE_DB_DATABASE} - MYSQL_USER: ${GONE_DB_USERNAME} - MYSQL_PASSWORD: ${GONE_DB_PASSWORD} - MYSQL_ROOT_PASSWORD: ${GONE_DB_PASSWORD} - ports: - - "${GONE_DB_PORT}:3306" - volumes: - - mysql_volume_bp:/var/lib/mysql - -volumes: - mysql_volume_bp: diff --git a/templates/db/postgres/db.go.tmpl b/templates/db/postgres/db.go.tmpl new file mode 100644 index 0000000..3422984 --- /dev/null +++ b/templates/db/postgres/db.go.tmpl @@ -0,0 +1,27 @@ +package db + +import ( + "database/sql" + "log" + + _ "github.com/lib/pq" +) + +var DB *sql.DB + +func Connect() { + connStr := "user=postgres password=postgres dbname=app_db sslmode=disable" + var err error + DB, err = sql.Open("postgres", connStr) + if err != nil { + log.Fatalf("✖ Failed to connect to PostgreSQL: %v", err) + } + log.Println("✓ Connected to PostgreSQL database") +} + +func Close() { + if DB != nil { + DB.Close() + log.Println("🔌 PostgreSQL connection closed") + } +} diff --git a/templates/db/postgres/docker-compose.yml.tmpl b/templates/db/postgres/docker-compose.yml.tmpl deleted file mode 100644 index 311b70c..0000000 --- a/templates/db/postgres/docker-compose.yml.tmpl +++ /dev/null @@ -1,15 +0,0 @@ -services: - psql_bp: - image: postgres:latest - restart: unless-stopped - environment: - POSTGRES_DB: ${GONE_DB_DATABASE} - POSTGRES_USER: ${GONE_DB_USERNAME} - POSTGRES_PASSWORD: ${GONE_DB_PASSWORD} - ports: - - "${GONE_DB_PORT}:5432" - volumes: - - psql_volume_bp:/var/lib/postgresql - -volumes: - psql_volume_bp: \ No newline at end of file diff --git a/templates/db/sqllite/db.go.tmpl b/templates/db/sqllite/db.go.tmpl new file mode 100644 index 0000000..2693850 --- /dev/null +++ b/templates/db/sqllite/db.go.tmpl @@ -0,0 +1,26 @@ +package db + +import ( + "database/sql" + "log" + + _ "github.com/mattn/go-sqlite3" +) + +var DB *sql.DB + +func Connect() { + var err error + DB, err = sql.Open("sqlite3", "app.db") + if err != nil { + log.Fatalf("✖ Failed to connect to SQLite: %v", err) + } + log.Println("✓ Connected to SQLite database") +} + +func Close() { + if DB != nil { + DB.Close() + log.Println("🔌 SQLite connection closed") + } +} diff --git a/templates/embed.go b/templates/embed.go index 068db6d..5d7a80e 100644 --- a/templates/embed.go +++ b/templates/embed.go @@ -7,8 +7,7 @@ import "embed" // Since this file is located in the 'templates' directory, // the paths 'common' and 'rest' correctly refer to the template folders. // - -//go:embed common/** -//go:embed rest/** -//go:embed db/** +//go:embed common +//go:embed rest +//go:embed db var FS embed.FS diff --git a/templates/rest/chi/cmd/main.go.tmpl b/templates/rest/chi/cmd/main.go.tmpl new file mode 100644 index 0000000..933fb29 --- /dev/null +++ b/templates/rest/chi/cmd/main.go.tmpl @@ -0,0 +1,28 @@ +package main + +import ( + "log" + "net/http" + + "{{.ModuleName}}/internal/config" + "{{.ModuleName}}/internal/router" + + "github.com/go-chi/chi/v5" +) + +func main() { + cfg := config.Load() + + r := chi.NewRouter() + router.RegisterRoutes(r) + + port := cfg.Port + if port == "" { + port = "8080" + } + + log.Printf("Starting server on :%s", port) + if err := http.ListenAndServe(":"+port, r); err != nil { + log.Fatal(err) + } +} diff --git a/templates/rest/chi/go.mod.tmpl b/templates/rest/chi/go.mod.tmpl new file mode 100644 index 0000000..84b2fb3 --- /dev/null +++ b/templates/rest/chi/go.mod.tmpl @@ -0,0 +1,5 @@ +module {{.ModuleName}} + +go 1.22 + +require github.com/go-chi/chi/v5 v5.0.11 diff --git a/templates/rest/chi/internal/config/config.go.tmpl b/templates/rest/chi/internal/config/config.go.tmpl new file mode 100644 index 0000000..326241b --- /dev/null +++ b/templates/rest/chi/internal/config/config.go.tmpl @@ -0,0 +1,20 @@ +package config + +import "os" + +type Config struct { + Port string +} + +func Load() Config { + return Config{ + Port: getEnv("APP_PORT", "8080"), + } +} + +func getEnv(key, fallback string) string { + if value, ok := os.LookupEnv(key); ok { + return value + } + return fallback +} diff --git a/templates/rest/chi/internal/handler/user_handler.go.tmpl b/templates/rest/chi/internal/handler/user_handler.go.tmpl new file mode 100644 index 0000000..6c5ca19 --- /dev/null +++ b/templates/rest/chi/internal/handler/user_handler.go.tmpl @@ -0,0 +1,16 @@ +package handler + +import ( + "encoding/json" + "net/http" + + "github.com/go-chi/chi/v5" +) + +func GetUser(w http.ResponseWriter, r *http.Request) { + id := chi.URLParam(r, "id") + json.NewEncoder(w).Encode(map[string]string{ + "id": id, + "name": "John Doe", + }) +} diff --git a/templates/rest/chi/internal/router/routes.go.tmpl b/templates/rest/chi/internal/router/routes.go.tmpl new file mode 100644 index 0000000..9cd014d --- /dev/null +++ b/templates/rest/chi/internal/router/routes.go.tmpl @@ -0,0 +1,11 @@ +package router + +import ( + handler "{{.ModuleName}}/internal/handler" + + "github.com/go-chi/chi/v5" +) + +func RegisterRoutes(r *chi.Mux) { + r.Get("/users/{id}", handler.GetUser) +} diff --git a/templates/rest/clean/cmd/main.go.tmpl b/templates/rest/clean/cmd/main.go.tmpl deleted file mode 100644 index 1008f94..0000000 --- a/templates/rest/clean/cmd/main.go.tmpl +++ /dev/null @@ -1,58 +0,0 @@ -package main - -import ( - "context" - "fmt" - "log" - "net/http" - "os/signal" - "syscall" - "time" - "{{.ModuleName}}/internal/server" -) - -func gracefulShutdown(apiServer *http.Server, done chan bool) { - // Create context that listens for the interrupt signal from the OS. - ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) - defer stop() - - // Listen for the interrupt signal. - <-ctx.Done() - - log.Println("shutting down gracefully, press Ctrl+C again to force") - stop() // Allow Ctrl+C to force shutdown - - // The context is used to inform the server it has 5 seconds to finish - // the request it is currently handling - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - if err := apiServer.Shutdown(ctx); err != nil { - log.Printf("Server forced to shutdown with error: %v", err) - } - - log.Println("Server exiting") - - // Notify the main goroutine that the shutdown is complete - done <- true -} - -func main() { - - server := router.NewServer() - - // Create a done channel to signal when the shutdown is complete - done := make(chan bool, 1) - - // Run graceful shutdown in a separate goroutine - go gracefulShutdown(server, done) - - err := server.ListenAndServe() - if err != nil && err != http.ErrServerClosed { - panic(fmt.Sprintf("http server error: %s", err)) - } - - // Wait for the graceful shutdown to complete - <-done - log.Println("Graceful shutdown complete.") -} - diff --git a/templates/rest/clean/docker-compose.yml.tmpl b/templates/rest/clean/docker-compose.yml.tmpl deleted file mode 100644 index 1a16578..0000000 --- a/templates/rest/clean/docker-compose.yml.tmpl +++ /dev/null @@ -1,15 +0,0 @@ -services: - {{.ServiceName}}: - image: {{.Image}} - restart: unless-stopped - - environment: | - - ports: - - "${GONE_DB_PORT}:5432" - - volumes: - - {{.Volume}} - -volumes: - {{.VolumeName}}: diff --git a/templates/rest/clean/internal/handler/example_handler.go.tmpl b/templates/rest/clean/internal/handler/example_handler.go.tmpl deleted file mode 100644 index 71f31dc..0000000 --- a/templates/rest/clean/internal/handler/example_handler.go.tmpl +++ /dev/null @@ -1,21 +0,0 @@ -package handler - -import ( - "{{.ModuleName}}/internal/service" - "net/http" - - "github.com/gin-gonic/gin" -) - -type {{.Entity}}Handler struct { - Service *service.{{.Entity}}Service -} - -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) { - {{.LowerEntity}}s, _ := h.Service.Get{{.Entity}}s() - c.JSON(http.StatusOK, {{.LowerEntity}}s) -} diff --git a/templates/rest/clean/internal/model/example_model.go.tmpl b/templates/rest/clean/internal/model/example_model.go.tmpl deleted file mode 100644 index 076a318..0000000 --- a/templates/rest/clean/internal/model/example_model.go.tmpl +++ /dev/null @@ -1,15 +0,0 @@ -package model - -import ( - "gorm.io/gorm" -) - -type {{.Entity}} struct { - gorm.Model - ID int `json:"id"` - Name string `json:"name"` -} - -func init() { - Register(&{{.Entity}}{}) -} \ No newline at end of file diff --git a/templates/rest/clean/internal/model/registory.go.tmpl b/templates/rest/clean/internal/model/registory.go.tmpl deleted file mode 100644 index 9648607..0000000 --- a/templates/rest/clean/internal/model/registory.go.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -package model - -var Registry []interface{} - -func Register(m interface{}) { - Registry = append(Registry, m) -} diff --git a/templates/rest/clean/internal/repository/example_repo.go.tmpl b/templates/rest/clean/internal/repository/example_repo.go.tmpl deleted file mode 100644 index d4fe1d1..0000000 --- a/templates/rest/clean/internal/repository/example_repo.go.tmpl +++ /dev/null @@ -1,24 +0,0 @@ -package repository - -import ( - "{{.ModuleName}}/internal/model" - "gorm.io/gorm" -) - -type {{.Entity}}Repo struct { - DB *gorm.DB -} - -func New{{.Entity}}Repo(db *gorm.DB) *{{.Entity}}Repo { - return &{{.Entity}}Repo{DB: db} -} - -func (r *{{.Entity}}Repo) FindAll() ([]model.{{.Entity}}, error) { - var {{.LowerEntity}}s []model.{{.Entity}} - err := r.DB.Find(&{{.LowerEntity}}s).Error - return {{.LowerEntity}}s, err -} - -func (r *{{.Entity}}Repo) Create({{.LowerEntity}}*model.{{.Entity}}) error { - return r.DB.Create({{.LowerEntity}}).Error -} diff --git a/templates/rest/clean/internal/server/routes.go.tmpl b/templates/rest/clean/internal/server/routes.go.tmpl deleted file mode 100644 index 7083f8e..0000000 --- a/templates/rest/clean/internal/server/routes.go.tmpl +++ /dev/null @@ -1,58 +0,0 @@ -package router - -import ( - "{{.ModuleName}}/internal/handler" - "{{.ModuleName}}/internal/repository" - "{{.ModuleName}}/internal/service" - {{.ImportRouter}} -) - -func (s *Server) RegisterRoutes() {{.HTTPHandler}} { - r := {{.Start}} - - r.{{.Get}}("/", s.HelloWorldHandler) - - r.{{.Get}}("/health", s.healthHandler) - - gormDB := s.db.GetDB() - - - api := r.Group("/api/v1") - - {{ if .Entities }} - {{ range $i, $entity := .Entities }} - {{ $upper := index $.UpperEntity $i }} - {{ $lower := $entity }} - - {{ printf "%sRepo := repository.New%sRepo(gormDB)" $lower $upper }} - {{ printf "%sService := service.New%sService(%sRepo)" $lower $upper $lower }} - {{ printf "%sHandler := handler.New%sHandler(%sService)" $lower $upper $lower }} - - {{ call $.ApiGroup $upper $.Get $lower }} - {{ end }} - {{ else }} - userRepo := repository.NewUserRepo(gormDB) - userService := service.NewUserService(userRepo) - userHandler := handler.NewUserHandler(userService) - - { - user := api.Group("/user") - { - user.GET("", userHandler.GetUsers) - } - } - {{ end }} - - return r -} - -func (s *Server) HelloWorldHandler({{.FullContext}}) {{.Returnable}} { - resp := make(map[string]string) - resp["message"] = "Hello World" - - {{.ReturnKeyword}} {{.ToTheClient}} resp) -} - -func (s *Server) healthHandler({{.FullContext}}) {{.Returnable}} { - {{.ReturnKeyword}} {{.ToTheClient}} s.db.Health()) -} diff --git a/templates/rest/clean/internal/server/server.go.tmpl b/templates/rest/clean/internal/server/server.go.tmpl deleted file mode 100644 index 00614e3..0000000 --- a/templates/rest/clean/internal/server/server.go.tmpl +++ /dev/null @@ -1,50 +0,0 @@ -package router - -import ( - "fmt" - "net/http" - "os" - "strconv" - {{- if .DBType }} - database "{{.ModuleName}}/internal/db" - {{- end }} - "time" - - "gorm.io/gorm" -) - -type Server struct { - port int - db database.Service - gormDB *gorm.DB -} - -func NewServer() *http.Server { - port, _ := strconv.Atoi(os.Getenv("PORT")) - - dbService := database.New() - if dbService == nil { - panic("database.New() returned nil — DB initialization failed") - } - - gormDB := dbService.GetDB() - if gormDB == nil { - panic("dbService.GetDB() returned nil — Gorm DB is not initialized") - } - - srv := &Server{ - port: port, - db: dbService, - gormDB: gormDB, - } - - httpServer := &http.Server{ - Addr: fmt.Sprintf(":%d", srv.port), - Handler: srv.RegisterRoutes(), - IdleTimeout: time.Minute, - ReadTimeout: 10 * time.Second, - WriteTimeout: 30 * time.Second, - } - - return httpServer -} diff --git a/templates/rest/clean/internal/service/example_service.go.tmpl b/templates/rest/clean/internal/service/example_service.go.tmpl deleted file mode 100644 index d1d493f..0000000 --- a/templates/rest/clean/internal/service/example_service.go.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -package service - -import ( - "{{.ModuleName}}/internal/model" - "{{.ModuleName}}/internal/repository" -) - -type {{.Entity}}Service struct { - Repo *repository.{{.Entity}}Repo -} - -func New{{.Entity}}Service(repo *repository.{{.Entity}}Repo) *{{.Entity}}Service { - return &{{.Entity}}Service{Repo: repo} -} - -func (s *{{.Entity}}Service) Get{{.Entity}}s() ([]model.{{.Entity}}, error) { - return s.Repo.FindAll() -} \ No newline at end of file diff --git a/templates/rest/gin/cmd/main.go.tmpl b/templates/rest/gin/cmd/main.go.tmpl new file mode 100644 index 0000000..f321e65 --- /dev/null +++ b/templates/rest/gin/cmd/main.go.tmpl @@ -0,0 +1,36 @@ +package main + +import ( + "log" + + "{{.ModuleName}}/internal/config" + "{{.ModuleName}}/internal/router" + + "github.com/gin-gonic/gin" + + {{- if .DBType }} + "{{.ModuleName}}/internal/db" + {{- end }} +) + +func main() { + cfg := config.New() + + {{- if .DBType }} + db.Connect() + defer db.Close() + {{- end }} + + r := gin.Default() + router.RegisterRoutes(r) + + port := cfg.Port + if port == "" { + port = "{{.PortName}}" + } + + log.Printf("🚀 starting server on :%s", port) + if err := r.Run(":" + port); err != nil { + log.Fatal(err) + } +} diff --git a/templates/rest/clean/go.mod.tmpl b/templates/rest/gin/go.mod.tmpl similarity index 100% rename from templates/rest/clean/go.mod.tmpl rename to templates/rest/gin/go.mod.tmpl diff --git a/templates/rest/clean/internal/config/config.go.tmpl b/templates/rest/gin/internal/config/config.go.tmpl similarity index 100% rename from templates/rest/clean/internal/config/config.go.tmpl rename to templates/rest/gin/internal/config/config.go.tmpl diff --git a/templates/rest/gin/internal/handler/user_handler.go.tmpl b/templates/rest/gin/internal/handler/user_handler.go.tmpl new file mode 100644 index 0000000..07af570 --- /dev/null +++ b/templates/rest/gin/internal/handler/user_handler.go.tmpl @@ -0,0 +1,32 @@ +package handler + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + +type User struct { + ID int `json:"id"` + Name string `json:"name"` +} + +var users = []User{ + {ID: 1, Name: "Alice"}, + {ID: 2, Name: "Bob"}, +} + +func GetUsers(c *gin.Context) { + c.JSON(http.StatusOK, users) +} + +func CreateUser(c *gin.Context) { + var newUser User + if err := c.BindJSON(&newUser); err != nil { + c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) + return + } + newUser.ID = len(users) + 1 + users = append(users, newUser) + c.JSON(http.StatusCreated, newUser) +} diff --git a/templates/rest/gin/internal/router/routes.go.tmpl b/templates/rest/gin/internal/router/routes.go.tmpl new file mode 100644 index 0000000..50a950e --- /dev/null +++ b/templates/rest/gin/internal/router/routes.go.tmpl @@ -0,0 +1,15 @@ +package router + +import ( + "{{ .ModuleName }}/internal/handler" + + "github.com/gin-gonic/gin" +) + +func RegisterRoutes(r *gin.Engine) { + v1 := r.Group("/api/v1") + { + v1.GET("/users", handler.GetUsers) + v1.POST("/users", handler.CreateUser) + } +}