From 13702d117a2fc51cd198b01dc8def92e0755ff29 Mon Sep 17 00:00:00 2001 From: Suraj B M Date: Mon, 22 Sep 2025 21:13:17 +0530 Subject: [PATCH] feat: add init command and setup db --- cmd/init.go | 71 ++++++++++++++++++++++++++++++++++++++++++++++ cmd/root.go | 15 ++-------- cmd/utils/db.go | 44 ++++++++++++++++++++++++++++ cmd/utils/tools.go | 13 +++++++++ go.mod | 9 ++++-- go.sum | 15 ++++++++++ main.go | 7 +++-- 7 files changed, 157 insertions(+), 17 deletions(-) create mode 100644 cmd/init.go create mode 100644 cmd/utils/db.go create mode 100644 cmd/utils/tools.go diff --git a/cmd/init.go b/cmd/init.go new file mode 100644 index 0000000..2de9ba3 --- /dev/null +++ b/cmd/init.go @@ -0,0 +1,71 @@ +/* +Copyright © 2025 NAME HERE +*/ +package cmd + +import ( + "envy/cmd/utils" + "fmt" + "os" + "path" + + "github.com/spf13/cobra" +) + +// initCmd represents the init command +var initCmd = &cobra.Command{ + Use: "init", + Short: "Initialize envy on your system", + Run: func(cmd *cobra.Command, args []string) { + config, err := os.UserConfigDir() + if err != nil { + fmt.Println(utils.ErrStyle.Render("Config directory not found for your OS. Please run `envy init `.")) + return + } + + envyPath := path.Join(config, "envy") + + _, err = os.Stat(envyPath) + + if os.IsExist(err) { + fmt.Println(utils.ErrStyle.Render("Config directory already exists.")) + return + } + + err = os.Mkdir(envyPath, 0755) + if err != nil { + fmt.Println(utils.ErrStyle.Render("Failed to create config directory:", err.Error())) + } + + configFile, err := os.Create(path.Join(envyPath, "config.toml")) + if err != nil { + fmt.Println(utils.ErrStyle.Render("Failed to create config file:", err.Error())) + } + defer configFile.Close() + + _, err = os.Create(path.Join(envyPath, "envy.db")) + if err != nil { + fmt.Println(utils.ErrStyle.Render("Failed to create database file:", err.Error())) + } + + utils.Migrate() + + configFile.Write([]byte("[config]\nmode = \"local\"\n")) + + fmt.Println("envy initialized on your system.") + }, +} + +func init() { + rootCmd.AddCommand(initCmd) + + // Here you will define your flags and configuration settings. + + // Cobra supports Persistent Flags which will work for this command + // and all subcommands, e.g.: + // initCmd.PersistentFlags().String("foo", "", "A help for foo") + + // Cobra supports local flags which will only run when this command + // is called directly, e.g.: + // initCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") +} diff --git a/cmd/root.go b/cmd/root.go index 6baf8e2..f5f3d9b 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -1,6 +1,5 @@ /* -Copyright © 2025 NAME HERE - +Copyright © 2025 Suraj B M */ package cmd @@ -10,18 +9,10 @@ import ( "github.com/spf13/cobra" ) - - // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ Use: "envy", - Short: "A brief description of your application", - Long: `A longer description that spans multiple lines and likely contains -examples and usage of using your application. For example: - -Cobra is a CLI library for Go that empowers applications. -This application is a tool to generate the needed files -to quickly create a Cobra application.`, + Short: "A CLI tool to manage .env files for your projects", // Uncomment the following line if your bare application // has an action associated with it: // Run: func(cmd *cobra.Command, args []string) { }, @@ -47,5 +38,3 @@ func init() { // when this action is called directly. rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle") } - - diff --git a/cmd/utils/db.go b/cmd/utils/db.go new file mode 100644 index 0000000..9aa71b8 --- /dev/null +++ b/cmd/utils/db.go @@ -0,0 +1,44 @@ +package utils + +import ( + "fmt" + "os" + "path" + + "gorm.io/driver/sqlite" + "gorm.io/gorm" +) + +type Project struct { + ID uint `gorm:"primaryKey"` + Name string + Environments []Environment +} + +type Environment struct { + ID uint `gorm:"primaryKey"` + Name string + Data string + Active bool + ProjectID uint + Project Project `gorm:"constraint:OnUpdate:CASCADE,OnDelete:SET NULL;"` +} + +var DB *gorm.DB + +func Init() { + config, err := os.UserConfigDir() + if err != nil { + fmt.Println(ErrStyle.Render("Error accessing config directory:", err.Error())) + return + } + + DB, err = gorm.Open(sqlite.Open(path.Join(config, "envy.db")), &gorm.Config{}) + if err != nil { + ErrPrint("Error while opening database:" + err.Error()) + } +} + +func Migrate() { + DB.AutoMigrate(&Project{}, &Environment{}) +} diff --git a/cmd/utils/tools.go b/cmd/utils/tools.go new file mode 100644 index 0000000..7b2b598 --- /dev/null +++ b/cmd/utils/tools.go @@ -0,0 +1,13 @@ +package utils + +import ( + "fmt" + + "github.com/charmbracelet/lipgloss" +) + +var ErrStyle = lipgloss.NewStyle().Foreground(lipgloss.Color("#F00")) + +func ErrPrint(data string) { + fmt.Println(ErrStyle.Render(data)) +} diff --git a/go.mod b/go.mod index ec41175..cb5ee97 100644 --- a/go.mod +++ b/go.mod @@ -18,10 +18,13 @@ require ( github.com/dustin/go-humanize v1.0.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/jinzhu/inflection v1.0.0 // indirect + github.com/jinzhu/now v1.1.5 // 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/mattn/go-sqlite3 v1.14.32 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect @@ -30,9 +33,11 @@ require ( github.com/spf13/cobra v1.10.1 // indirect github.com/spf13/pflag v1.0.9 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/sync v0.15.0 // indirect + golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.33.0 // indirect - golang.org/x/text v0.23.0 // indirect + golang.org/x/text v0.29.0 // indirect + gorm.io/driver/sqlite v1.6.0 // indirect + gorm.io/gorm v1.31.0 // indirect ) replace github.com/charmbracelet/huh => github.com/silicoflare/huh v0.0.0-20250921143325-6504e5f1a84d diff --git a/go.sum b/go.sum index 9e6723e..1744868 100644 --- a/go.sum +++ b/go.sum @@ -18,6 +18,7 @@ github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoF github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= github.com/charmbracelet/x/ansi v0.8.0 h1:9GTq3xq9caJW8ZrBTe0LIe2fvfLR/bYXKTx2llXn7xE= github.com/charmbracelet/x/ansi v0.8.0/go.mod h1:wdYl/ONOLHLIVmQaxbIYEC/cRKOQyjTkowiI4blgS9Q= +github.com/charmbracelet/x/ansi v0.9.3 h1:BXt5DHS/MKF+LjuK4huWrC6NCvHtexww7dMayh6GXd0= github.com/charmbracelet/x/ansi v0.9.3/go.mod h1:3RQDQ6lDnROptfpWuUVIUG64bD2g2BgntdxH0Ya5TeE= github.com/charmbracelet/x/cellbuf v0.0.13 h1:/KBBKHuVRbq1lYx5BzEHBAFBP8VcQzJejZ/IA3iR28k= github.com/charmbracelet/x/cellbuf v0.0.13/go.mod h1:xe0nKWGd3eJgtqZRaN9RjMtK7xUYchjzPr7q6kcvCCs= @@ -32,6 +33,10 @@ github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6 github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= +github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= 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= @@ -40,6 +45,8 @@ github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2J 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/mattn/go-sqlite3 v1.14.32 h1:JD12Ag3oLy1zQA+BNn74xRgaBbdhbNIDYvQUEuuErjs= +github.com/mattn/go-sqlite3 v1.14.32/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= @@ -62,12 +69,20 @@ github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJu golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw= golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= 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.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik= golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY= golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= 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= +gorm.io/driver/sqlite v1.6.0 h1:WHRRrIiulaPiPFmDcod6prc4l2VGVWHz80KspNsxSfQ= +gorm.io/driver/sqlite v1.6.0/go.mod h1:AO9V1qIQddBESngQUKWL9yoH93HIeA1X6V633rBwyT8= +gorm.io/gorm v1.31.0 h1:0VlycGreVhK7RF/Bwt51Fk8v0xLiiiFdbGDPIZQ7mJY= +gorm.io/gorm v1.31.0/go.mod h1:XyQVbO2k6YkOis7C2437jSit3SsDK72s7n7rsSHd+Gs= diff --git a/main.go b/main.go index 850ddf7..ce16af2 100644 --- a/main.go +++ b/main.go @@ -1,11 +1,14 @@ /* Copyright © 2025 NAME HERE - */ package main -import "envy/cmd" +import ( + "envy/cmd" + "envy/cmd/utils" +) func main() { + utils.Migrate() cmd.Execute() }