package main import ( "context" "errors" "fmt" "log" "os" "time" "cmroubao/backend-api/internal/config" "cmroubao/backend-api/internal/platform/database" "cmroubao/backend-api/internal/platform/migration" ) func main() { if err := run(os.Args[1:]); err != nil { log.Printf("migration command failed: %v", err) os.Exit(1) } } func run(arguments []string) error { if len(arguments) != 1 { return errors.New("usage: migrate ") } command := arguments[0] if command != "up" && command != "down" && command != "status" { return errors.New("migration command must be up, down, or status") } databasePath, err := config.LoadDatabasePath(os.LookupEnv) if err != nil { return err } ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) defer cancel() db, err := database.Open(ctx, databasePath) if err != nil { return errors.New("database startup failed") } defer func() { if err := db.Close(); err != nil { log.Print("database close failed") } }() runner, err := migration.New(db) if err != nil { return errors.New("migration setup failed") } switch command { case "up": count, err := runner.Up(ctx) if err != nil { return errors.New("migration up failed") } fmt.Printf("applied=%d\n", count) case "down": if err := runner.Down(ctx); err != nil { return errors.New("migration down failed") } fmt.Println("rolled_back=1") case "status": statuses, err := runner.Status(ctx) if err != nil { return errors.New("migration status failed") } for _, status := range statuses { state := "pending" if status.Applied { state = "applied" } fmt.Printf("version=%d state=%s\n", status.Version, state) } } return nil }