diff --git a/cmd/limen/main.go b/cmd/limen/main.go index 71f1980..e3530cc 100644 --- a/cmd/limen/main.go +++ b/cmd/limen/main.go @@ -74,6 +74,12 @@ func main() { Aliases: []string{"c"}, Required: true, }, + &cli.StringFlag{ + Name: "format", + Usage: "SQL format name (golang-migrate, goose)", + Aliases: []string{"f"}, + Value: "golang-migrate", + }, }, Action: runMigrateGenerate, }, @@ -126,6 +132,7 @@ func runMigrateGenerate(ctx context.Context, cmd *cli.Command) error { outputPath := cmd.String("output") driverName := cmd.String("driver") dsn := cmd.String("dsn") + sqlFormat := cmd.String("format") config, err := loadConfig(schemasPath) if err != nil { @@ -141,6 +148,18 @@ func runMigrateGenerate(ctx context.Context, cmd *cli.Command) error { return fmt.Errorf("dsn is required") } + var sqlFileWriter SqlFileWriter + switch sqlFormat { + case "golang-migrate": + sqlFileWriter = &GolangMigrateCompatibleSqlWriter{} + case "goose": + sqlFileWriter = &GooseCompatibleSqlWriter{} + } + + if sqlFileWriter == nil { + return fmt.Errorf("unsupported format") + } + var migrations []Migration db, err := driver.Connect(dsn) @@ -162,18 +181,9 @@ func runMigrateGenerate(ctx context.Context, cmd *cli.Command) error { continue } - upFile := filepath.Join(outputPath, fmt.Sprintf("%s.up.sql", migration.Version)) - downFile := filepath.Join(outputPath, fmt.Sprintf("%s.down.sql", migration.Version)) - - if err := os.WriteFile(upFile, []byte(migration.UpSQL), 0644); err != nil { - return fmt.Errorf("error writing migration file: %w", err) + if err := sqlFileWriter.WriteSqlFile(outputPath, migration); err != nil { + return err } - - if err := os.WriteFile(downFile, []byte(migration.DownSQL), 0644); err != nil { - return fmt.Errorf("error writing migration file: %w", err) - } - - fmt.Printf("Generated migration: %s\n", migration.Version) } fmt.Println("\nTo apply these migrations, use any other migration tool that supports SQL files like goose, golang-migrate, etc. Or apply them manually.") diff --git a/cmd/limen/sql_file_writer.go b/cmd/limen/sql_file_writer.go new file mode 100644 index 0000000..da82a50 --- /dev/null +++ b/cmd/limen/sql_file_writer.go @@ -0,0 +1,56 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" +) + +type SqlFileWriter interface { + WriteSqlFile(outputPath string, migration Migration) error +} + +type GolangMigrateCompatibleSqlWriter struct{} + +func (w *GolangMigrateCompatibleSqlWriter) WriteSqlFile(outputPath string, migration Migration) error { + upFile := filepath.Join(outputPath, fmt.Sprintf("%s.up.sql", migration.Version)) + downFile := filepath.Join(outputPath, fmt.Sprintf("%s.down.sql", migration.Version)) + + if err := os.WriteFile(upFile, []byte(migration.UpSQL), 0644); err != nil { + return fmt.Errorf("error writing migration file: %w", err) + } + + if err := os.WriteFile(downFile, []byte(migration.DownSQL), 0644); err != nil { + return fmt.Errorf("error writing migration file: %w", err) + } + + return nil +} + +type GooseCompatibleSqlWriter struct{} + +const gooseMigrationUpAnnotation string = "-- +goose Up" +const gooseMigrationDownAnnotation string = "-- +goose Down" + +func (w *GooseCompatibleSqlWriter) WriteSqlFile(outputPath string, migration Migration) error { + file := filepath.Join(outputPath, fmt.Sprintf("%s.sql", migration.Version)) + + sql := strings.Join( + []string{ + gooseMigrationUpAnnotation, + migration.UpSQL, + gooseMigrationDownAnnotation, + migration.DownSQL, + }, + "\n", + ) + + sql += "\n" // Adding endline at the end of the file as a good practice + + if err := os.WriteFile(file, []byte(sql), 0644); err != nil { + return fmt.Errorf("error writing migration file: %w", err) + } + + return nil +}