package migrator import ( "database/sql" "fmt" "os" "text/tabwriter" "git.gocasts.ir/ebhomengo/niki/pkg/database/postgres" _ "github.com/jackc/pgx/v5/stdlib" migrate "github.com/rubenv/sql-migrate" ) type Config struct { migrationDBName string `koanf:"migration_db_name"` pathOfMigrations string `koanf:"pathOfMigrations"` dbConfig postgres.Config } type Migrator struct { cfg Config dialect string migrations *migrate.FileMigrationSource } func New(cfg Config) *Migrator { return &Migrator{ cfg: cfg, dialect: "psx", migrations: &migrate.FileMigrationSource{Dir: cfg.pathOfMigrations}, } } func (m *Migrator) getDsn() string { return fmt.Sprintf("host=%s user=%s password=%s dbname=%s sslmode=disable", m.cfg.dbConfig.Host, m.cfg.dbConfig.User, m.cfg.dbConfig.Password, m.cfg.dbConfig.DbName) } func (m *Migrator) Up() { db, err := sql.Open(m.dialect, m.getDsn()) if err != nil { panic(fmt.Errorf("can't open postgres db: %v", err)) } defer db.Close() if err != nil { return } n, err := migrate.Exec(db, m.dialect, m.migrations, migrate.Up) if err != nil { panic(fmt.Errorf("cant apply migrations : %v ", err)) } fmt.Printf("Applied %d migrations\n", n) } func (m *Migrator) Down() { migrate.SetTable(m.cfg.migrationDBName) db, err := sql.Open(m.dialect, m.getDsn()) if err != nil { panic(fmt.Errorf("can't open postgres db: %v", err)) } defer db.Close() n, err := migrate.Exec(db, m.dialect, m.migrations, migrate.Down) if err != nil { panic(fmt.Errorf("cant rollback migrations : %v ", err)) } fmt.Printf("Applied %d migrations\n", n) } func (m *Migrator) Status() { migrate.SetTable(m.cfg.migrationDBName) db, err := sql.Open(m.dialect, m.getDsn()) if err != nil { panic(fmt.Errorf("can't open postgres db: %v", err)) } defer db.Close() migrations, _, err := migrate.PlanMigration(db, m.dialect, m.migrations, migrate.Up, 0) if err != nil { panic(fmt.Errorf("can't plan migrations: %v", err)) } if len(migrations) == 0 { fmt.Println("✅ No pending migrations.") return } w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) fmt.Fprintln(w, "PENDING MIGRATIONS") fmt.Fprintln(w, "ID\tSTATUS") for _, migration := range migrations { fmt.Fprintf(w, "%s\tPending\n", migration.Id) } w.Flush() }