package migrate import ( "fmt" "io/fs" "os" "path/filepath" "sort" "strings" ) type Direction string const ( Up Direction = "up" Down Direction = "down" ) type Migration struct { Name string Path string SQL string } type Runner struct { Dir string } func (r Runner) Load(direction Direction) ([]Migration, error) { var files []string err := filepath.WalkDir(r.Dir, func(path string, d fs.DirEntry, err error) error { if err != nil { return err } if d.IsDir() { return nil } base := filepath.Base(path) extMatch := strings.HasSuffix(base, fmt.Sprintf(".%s.sql", direction)) flatMatch := base == fmt.Sprintf("%s.sql", direction) if extMatch || flatMatch { files = append(files, path) } return nil }) if err != nil { return nil, err } sort.Strings(files) if direction == Down { reverse(files) } migrations := make([]Migration, 0, len(files)) for _, path := range files { raw, err := os.ReadFile(path) if err != nil { return nil, err } migrations = append(migrations, Migration{ Name: strings.TrimPrefix(path, r.Dir+string(filepath.Separator)), Path: path, SQL: string(raw), }) } return migrations, nil } func reverse[T any](values []T) { for i, j := 0, len(values)-1; i < j; i, j = i+1, j-1 { values[i], values[j] = values[j], values[i] } }