package main import ( "database/sql" "flag" "fmt" "log" "os" "os/exec" "path" "strings" "text/template" "time" "github.com/pressly/goose/v3" _ "modernc.org/sqlite" ) func openInEditor(filePath string) error { editor := os.Getenv("EDITOR") if editor == "" { editor = "vim" } cmd := exec.Command(editor, filePath) cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Start() return cmd.Wait() } const ( migrationType = "sql" migrationDir = "db/migrations" ) func main() { flag.Parse() db, err := sql.Open("sqlite", "db/sqlite.db") if err != nil { log.Fatalf("failed to connect to db: %v", err) } defer db.Close() if err := goose.SetDialect("sqlite"); err != nil { log.Fatalf("failed to set goose db dialect: %v", err) } switch flag.Arg(0) { case "create": name := flag.Arg(1) if name == "" { log.Fatalf("no migration name provided") } tmpl, _ := template.New("query").Parse(`-- +goose Up -- +goose StatementBegin SELECT * FROM table; -- +goose StatementEnd -- +goose Down -- +goose StatementBegin SELECT * FROM table; -- +goose StatementEnd `) now := time.Now().UTC() if err := goose.CreateWithTemplate(db, migrationDir, tmpl, name, migrationType); err != nil { log.Fatalf("failed to generate new migration: %v", err) } fileName := fmt.Sprintf("%d%02d%02d%02d%02d%02d_%s.%s", now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute(), now.Second(), strings.ToLower(name), migrationType) fmt.Printf("fileName: %v\n", fileName) if err := openInEditor(path.Join(migrationDir, fileName)); err != nil { log.Fatalf("failed to open migration file in editor: %v", err) } case "up": if err := goose.Up(db, migrationDir); err != nil { log.Fatalf("failed to upgrade to latest migration: %v", err) } case "down": if err := goose.Down(db, migrationDir); err != nil { log.Fatalf("failed to downgrade to previous migration: %v", err) } case "status": if err := goose.Status(db, migrationDir); err != nil { log.Fatalf("failed to get status: %v", err) } default: log.Fatalf("unknown command: %v", flag.Arg(0)) } }