rorm_cli/
entry.rs

1use clap::{ArgAction, Parser, Subcommand};
2
3use crate::init::init;
4use crate::make_migrations::{run_make_migrations, MakeMigrationsOptions};
5use crate::migrate::{run_migrate, MigrateOptions};
6use crate::squash_migrations::squash_migrations;
7
8#[derive(Subcommand)]
9pub enum InitDriver {
10    #[cfg(feature = "sqlite")]
11    #[clap(about = "Initialize a sqlite configuration")]
12    Sqlite {
13        #[clap(long = "filename")]
14        #[clap(default_value_t = String::from("db.sqlite3"))]
15        #[clap(help = "Name of the sqlite file.")]
16        filename: String,
17    },
18    #[cfg(feature = "mysql")]
19    #[clap(about = "Initialize a mysql configuration")]
20    Mysql {
21        #[clap(long = "host")]
22        #[clap(default_value_t = String::from("127.0.0.1"))]
23        #[clap(help = "The address to use to connect to the database.")]
24        host: String,
25        #[clap(long = "port")]
26        #[clap(default_value_t = 5432)]
27        #[clap(help = "The port to use to connect to the database.")]
28        port: u16,
29        #[clap(long = "user")]
30        #[clap(default_value_t = String::from("dbuser"))]
31        #[clap(help = "The user to use to connect to the database.")]
32        user: String,
33        #[clap(long = "password")]
34        #[clap(
35            help = "Set the password. To minimize the risk of exposing your password, use --ask-password instead."
36        )]
37        password: Option<String>,
38        #[clap(long = "ask-password")]
39        #[clap(
40            help = "Ask for the password for the database. If specified with the --password option, this value will be prevalent."
41        )]
42        ask_password: bool,
43        #[clap(long = "name")]
44        #[clap(default_value_t = String::from("dbname"))]
45        #[clap(help = "The name of the database to connect to.")]
46        name: String,
47    },
48    #[cfg(feature = "postgres")]
49    #[clap(about = "Initialize a postgres configuration")]
50    Postgres {
51        #[clap(long = "host")]
52        #[clap(default_value_t = String::from("127.0.0.1"))]
53        #[clap(help = "The address to use to connect to the database.")]
54        host: String,
55        #[clap(long = "port")]
56        #[clap(default_value_t = 5432)]
57        #[clap(help = "The port to use to connect to the database.")]
58        port: u16,
59        #[clap(long = "user")]
60        #[clap(default_value_t = String::from("dbuser"))]
61        #[clap(help = "The user to use to connect to the database.")]
62        user: String,
63        #[clap(long = "password")]
64        #[clap(
65            help = "Set the password. To minimize the risk of exposing your password, use --ask-password instead."
66        )]
67        password: Option<String>,
68        #[clap(long = "ask-password")]
69        #[clap(
70            help = "Ask for the password for the database. If specified with the --password option, this value will be prevalent."
71        )]
72        ask_password: bool,
73        #[clap(long = "name")]
74        #[clap(default_value_t = String::from("dbname"))]
75        #[clap(help = "The name of the database to connect to.")]
76        name: String,
77    },
78}
79
80#[derive(Subcommand)]
81enum Commands {
82    #[clap(about = "Create the database configuration file")]
83    Init {
84        #[clap(long = "database-config")]
85        #[clap(default_value_t = String::from("./database.toml"))]
86        #[clap(help = "Path to the database configuration file that should be created.")]
87        database_config: String,
88
89        #[clap(short = 'f', long = "force")]
90        #[clap(help = "Overwrite the database configuration if it is existent already")]
91        force: bool,
92
93        #[clap(subcommand)]
94        driver: InitDriver,
95    },
96
97    #[clap(about = "Tool to create migrations")]
98    MakeMigrations {
99        #[clap(long = "models-file")]
100        #[clap(default_value_t=String::from("./.models.json"))]
101        #[clap(help = "Location of the intermediate representation of models.")]
102        models_file: String,
103
104        #[clap(short = 'm', long = "migration-dir")]
105        #[clap(default_value_t=String::from("./migrations/"))]
106        #[clap(help = "Destination to / from which migrations are written / read.")]
107        migration_dir: String,
108
109        #[clap(help = "Use this name as migration name instead of generating one.")]
110        name: Option<String>,
111
112        #[clap(long = "non-interactive")]
113        #[clap(action = ArgAction::SetTrue)]
114        #[clap(help = "If set, no questions will be asked.")]
115        non_interactive: bool,
116
117        #[clap(long = "disable-warnings")]
118        #[clap(action = ArgAction::SetTrue)]
119        #[clap(help = "If set, no warnings will be printed.")]
120        warnings_disabled: bool,
121    },
122
123    #[clap(about = "Apply migrations")]
124    Migrate {
125        #[clap(short = 'm', long = "migration-dir")]
126        #[clap(default_value_t=String::from("./migrations/"))]
127        #[clap(help = "Destination to / from which migrations are written / read.")]
128        migration_dir: String,
129
130        #[clap(long = "database-config")]
131        #[clap(default_value_t=String::from("./database.toml"))]
132        #[clap(help = "Path to the database configuration file.")]
133        database_config: String,
134
135        #[clap(long = "log-sql")]
136        #[clap(action = ArgAction::SetTrue)]
137        #[clap(help = "If turned on, all queries to the database will be logged")]
138        log_queries: bool,
139
140        #[clap(long = "apply-until")]
141        #[clap(id = "MIGRATION_ID")]
142        #[clap(help = "Only apply the migrations to (inclusive) the given migration.")]
143        apply_until: Option<u16>,
144    },
145
146    #[clap(about = "Squash migrations")]
147    SquashMigrations {
148        #[clap(short = 'm', long = "migration-dir")]
149        #[clap(default_value_t = String::from("./migrations/"))]
150        #[clap(help = "Destination to / from which migrations are written / read.")]
151        migration_dir: String,
152
153        #[clap(help = "First migration to start squashing from.")]
154        first_migration: u16,
155
156        #[clap(help = "Last migration to squash.")]
157        last_migration: u16,
158    },
159
160    #[clap(about = "Merge migrations")]
161    MergeMigrations {},
162}
163
164#[derive(Parser)]
165#[clap(version, about = "CLI tool for rorm", long_about = None)]
166#[clap(arg_required_else_help = true)]
167#[clap(name = "rorm-cli")]
168pub struct Cli {
169    #[clap(subcommand)]
170    command: Option<Commands>,
171}
172
173pub async fn entry(cli: Cli) -> anyhow::Result<()> {
174    match cli.command {
175        Some(Commands::Init {
176            force,
177            driver,
178            database_config,
179        }) => init(database_config, driver, force)?,
180        Some(Commands::MakeMigrations {
181            models_file,
182            migration_dir,
183            name,
184            non_interactive,
185            warnings_disabled,
186        }) => {
187            run_make_migrations(MakeMigrationsOptions {
188                models_file,
189                migration_dir,
190                name,
191                non_interactive,
192                warnings_disabled,
193            })?;
194        }
195        Some(Commands::Migrate {
196            migration_dir,
197            database_config,
198            log_queries,
199            apply_until,
200        }) => {
201            run_migrate(MigrateOptions {
202                migration_dir,
203                database_config,
204                log_queries,
205                apply_until,
206            })
207            .await?;
208        }
209        Some(Commands::SquashMigrations {
210            migration_dir,
211            first_migration,
212            last_migration,
213        }) => {
214            squash_migrations(migration_dir, first_migration, last_migration).await?;
215        }
216        _ => {}
217    }
218
219    Ok(())
220}