package main import ( "context" "embed" "errors" "flag" "fmt" "io/fs" "log" "os" "path/filepath" "time" "go.mongodb.org/mongo-driver/v2/mongo" "go.mongodb.org/mongo-driver/v2/mongo/options" "tangled.org/softprops.tngl.sh/moose" _ "tangled.org/softprops.tngl.sh/moose/example/migrations" // triggers go script init ) //go:embed migrations/*.json migrations/*.go var embedMigrations embed.FS func main() { log.SetFlags(0) var db string var uri string flags := flag.NewFlagSet("example", flag.ExitOnError) flags.StringVar(&db, "db", "example", "db to apply and record migrations") flags.StringVar(&uri, "uri", "mongodb://127.0.0.1:27017", "MongoDB connection string") if err := flags.Parse(os.Args[1:]); err != nil { log.Fatalf("moose: failed to parse flags: %v", err) } args := flags.Args() if len(args) == 0 { _, _ = fmt.Fprintf(os.Stderr, "example: please provide a command to run. Supported commands: create, up, status\n") os.Exit(1) } if err := run(args[0], uri, db, args[1:]); err != nil { _, _ = fmt.Fprintf(os.Stderr, "example %s\n", err) os.Exit(1) } } func run(cmd, uri, db string, args []string) error { dir := "migrations" client, err := mongo.Connect(options.Client().ApplyURI(uri).SetConnectTimeout(1 * time.Second)) if err != nil { return nil } defer func() { _ = client.Disconnect(context.Background()) }() ctx := context.Background() dirfs, err := fs.Sub(embedMigrations, dir) if err != nil { return err } provider, err := moose.NewProvider(client.Database(db), dirfs) if err != nil { return err } switch cmd { case "create": if len(args) == 0 { return errors.New("create must be of the form: moose [OPTIONS] create NAME") } file, err := moose.Create(dir, args[1], "go", true) if err != nil { return err } fmt.Printf("Created new migration file: %s\n", file) case "up": results, err := provider.Up(ctx) if err != nil { return err } for _, r := range results { fmt.Println(r) } case "down": res, err := provider.Down(ctx) if err != nil { return err } fmt.Println(res) case "status": results, err := provider.Status(ctx) if err != nil { return err } log.Printf(" Applied At Migration") log.Printf(" =======================================") for _, r := range results { appliedAt := "Pending" if !r.AppliedAt.IsZero() { appliedAt = r.AppliedAt.Format(time.ANSIC) } log.Printf(" %-24s -- %v", appliedAt, filepath.Base(r.Source.Path)) } } return nil }