db_migrate/commands/
up.rs1use crate::{migration::MigrationManager, CommandOutput};
2use anyhow::Result;
3use clap::Args;
4use colored::*;
5
6#[derive(Args)]
7pub struct UpCommand {
8 #[arg(short, long)]
10 count: Option<usize>,
11
12 #[arg(long)]
14 dry_run: bool,
15}
16
17impl UpCommand {
18 pub async fn execute(&self, manager: &mut MigrationManager) -> Result<CommandOutput> {
19 let pending_migrations = manager.get_pending_migrations().await?;
20
21 if pending_migrations.is_empty() {
22 return Ok(CommandOutput::success(format!(
23 "{} No pending migrations found",
24 "✅".green()
25 )));
26 }
27
28 let migrations_to_apply = if let Some(count) = self.count {
30 pending_migrations.into_iter().take(count).collect()
31 } else {
32 pending_migrations
33 };
34
35 if self.dry_run {
36 return self.show_dry_run(&migrations_to_apply);
37 }
38
39 let mut applied_count = 0;
40 let mut applied_migrations = Vec::new();
41
42 for migration in &migrations_to_apply {
43 match manager.apply_migration(migration).await {
44 Ok(_) => {
45 applied_count += 1;
46 applied_migrations.push(&migration.version);
47 println!(
48 "{} Applied migration: {}",
49 "✅".green(),
50 migration.version.bright_cyan()
51 );
52 }
53 Err(e) => {
54 return Ok(CommandOutput::success_with_data(
55 format!(
56 "{} Applied {} migration(s), failed on: {}",
57 if applied_count > 0 { "⚠️ " } else { "❌" },
58 applied_count,
59 migration.version
60 ),
61 serde_json::json!({
62 "applied_count": applied_count,
63 "applied_migrations": applied_migrations,
64 "failed_migration": migration.version,
65 "error": e.to_string()
66 })
67 ));
68 }
69 }
70 }
71
72 let message = if applied_count == 1 {
73 format!("{} Applied 1 migration successfully", "🎉".green())
74 } else {
75 format!("{} Applied {} migrations successfully", "🎉".green(), applied_count)
76 };
77
78 Ok(CommandOutput::success_with_data(
79 message,
80 serde_json::json!({
81 "applied_count": applied_count,
82 "applied_migrations": applied_migrations
83 })
84 ))
85 }
86
87 fn show_dry_run(&self, migrations: &[crate::MigrationFile]) -> Result<CommandOutput> {
88 let mut output = vec![
89 format!("{} Dry run mode - showing migrations that would be applied:", "🔍".cyan()),
90 String::new(),
91 ];
92
93 for (i, migration) in migrations.iter().enumerate() {
94 output.push(format!(
95 "{}. {} - {}",
96 i + 1,
97 migration.version.bright_cyan(),
98 migration.description
99 ));
100 }
101
102 if migrations.is_empty() {
103 output.push("No migrations would be applied.".to_string());
104 } else {
105 output.push(String::new());
106 output.push(format!(
107 "Total: {} migration(s) would be applied",
108 migrations.len()
109 ));
110 }
111
112 Ok(CommandOutput::success_with_data(
113 output.join("\n"),
114 serde_json::json!({
115 "dry_run": true,
116 "migrations_count": migrations.len(),
117 "migrations": migrations.iter().map(|m| {
118 serde_json::json!({
119 "version": m.version,
120 "description": m.description
121 })
122 }).collect::<Vec<_>>()
123 })
124 ))
125 }
126}