github.com/akkaraju-satvik/dbmap@v0.0.3-0.20240414054547-f818701a74f0/cmd/init.go (about) 1 package cmd 2 3 import ( 4 "database/sql" 5 "fmt" 6 "os" 7 "regexp" 8 "strings" 9 10 "github.com/akkaraju-satvik/dbmap/config" 11 "github.com/akkaraju-satvik/dbmap/queries" 12 "github.com/fatih/color" 13 "github.com/spf13/cobra" 14 15 _ "github.com/lib/pq" 16 ) 17 18 var initErrorStrings = map[string]string{ 19 "migrations": "Error creating migrations directory\n %s", 20 "config": "Error creating config file", 21 "table": "Error creating migrations table\n %s", 22 "db": "Could not find a database with the provided connection string\n %s", 23 "postgres": "Please provide a valid postgres connection string\n Example: postgres://user:password@localhost:5432/dbname\n", 24 } 25 26 var initCmd = &cobra.Command{ 27 Use: "init", 28 Short: "Initialize dbmap in a project directory", 29 Long: `Initializes dbmap in a project directory by creating a migrations directory and a config file. 30 31 The config file will contain the database connection string and the migrations directory path.`, 32 Run: func(cmd *cobra.Command, args []string) { 33 migrationsDir, err := cmd.Flags().GetString("migrations-dir") 34 if err != nil { 35 fmt.Println(err.Error()) 36 os.Exit(1) 37 } 38 connection, err := cmd.Flags().GetString("db-connection") 39 if err != nil { 40 color.Red(err.Error()) 41 os.Exit(1) 42 } 43 if connection == "" { 44 fmt.Printf("Enter the database connection string: ") 45 fmt.Scanln(&connection) 46 if connection == "" { 47 color.Red("Please provide a valid postgres connection string\n Example: postgres://user:password@localhost:5432/dbname\n") 48 os.Exit(1) 49 } 50 } 51 ssl, _ := cmd.Flags().GetBool("ssl") 52 if !strings.Contains(connection, "sslmode=require") && !ssl { 53 connection = connection + "?sslmode=disable" 54 } 55 err = initializeProject(migrationsDir, connection) 56 if err != nil { 57 color.Red(err.Error()) 58 os.Exit(1) 59 } 60 }, 61 } 62 63 func initializeProject(migrationsDir, connection string) error { 64 postgresConnStringRegex := regexp.MustCompile(`^postgres:\/\/.*\:.*@.*\/.*$`) 65 if !postgresConnStringRegex.MatchString(connection) { 66 return fmt.Errorf(initErrorStrings["postgres"]) 67 } 68 if migrationsDir == "" { 69 migrationsDir = "migrations" 70 } 71 err := os.MkdirAll(migrationsDir, 0755) 72 if err != nil { 73 removeSetup() 74 return fmt.Errorf(initErrorStrings["migrations"], err.Error()) 75 } 76 configFile, err := os.Create("dbmap.config.yaml") 77 if err != nil { 78 removeSetup() 79 return fmt.Errorf(initErrorStrings["config"]) 80 } 81 defer configFile.Close() 82 configFileContent := strings.Replace(config.ConfigFile, "$MIGRATIONS_DIR", migrationsDir, 1) 83 configFileContent = strings.Replace(configFileContent, "$DB_URL", connection, 1) 84 _, err = configFile.WriteString(configFileContent) 85 if err != nil { 86 removeSetup() 87 return fmt.Errorf(initErrorStrings["config"]) 88 } 89 db, err := sql.Open("postgres", connection) 90 if err != nil { 91 removeSetup() 92 return fmt.Errorf(initErrorStrings["db"], err.Error()) 93 } 94 defer db.Close() 95 _, err = db.Exec(queries.InitQuery) 96 if err != nil { 97 removeSetup() 98 return fmt.Errorf(initErrorStrings["table"], err.Error()) 99 } 100 color.Green("Setup complete") 101 return nil 102 } 103 104 func init() { 105 initCmd.Flags().StringP("migrations-dir", "d", "migrations", "Directory to store migration files") 106 initCmd.Flags().StringP("db-connection", "c", "", "Database connection string") 107 initCmd.Flags().BoolP("ssl", "s", false, "Use SSL for database connection") 108 rootCmd.AddCommand(initCmd) 109 } 110 111 func removeSetup() { 112 os.Remove("dbmap.config.yaml") 113 os.Remove("migrations") 114 }