prax_cli/cli.rs
1//! CLI argument definitions using clap.
2
3use clap::{Args, Parser, Subcommand, ValueEnum};
4use std::path::PathBuf;
5
6/// Prax CLI - A modern ORM for Rust
7#[derive(Parser, Debug)]
8#[command(name = "prax")]
9#[command(author = "Pegasus Heavy Industries LLC")]
10#[command(version)]
11#[command(about = "Prax CLI - A modern ORM for Rust", long_about = None)]
12#[command(propagate_version = true)]
13pub struct Cli {
14 /// Subcommand to execute
15 #[command(subcommand)]
16 pub command: Command,
17}
18
19/// Available CLI commands
20#[derive(Subcommand, Debug)]
21pub enum Command {
22 /// Initialize a new Prax project
23 Init(InitArgs),
24
25 /// Generate Rust client code from schema
26 Generate(GenerateArgs),
27
28 /// Schema validation and formatting
29 Validate(ValidateArgs),
30
31 /// Format schema file
32 Format(FormatArgs),
33
34 /// Database migration commands
35 Migrate(MigrateArgs),
36
37 /// Direct database operations
38 Db(DbArgs),
39
40 /// Display version information
41 Version,
42}
43
44// =============================================================================
45// Init Command
46// =============================================================================
47
48/// Arguments for the `init` command
49#[derive(Args, Debug)]
50pub struct InitArgs {
51 /// Path to initialize the project (defaults to current directory)
52 #[arg(default_value = ".")]
53 pub path: PathBuf,
54
55 /// Database provider to use
56 #[arg(short, long, default_value = "postgresql")]
57 pub provider: DatabaseProvider,
58
59 /// Database connection URL
60 #[arg(short, long)]
61 pub url: Option<String>,
62
63 /// Skip generating example schema
64 #[arg(long)]
65 pub no_example: bool,
66
67 /// Accept all defaults without prompting
68 #[arg(short, long)]
69 pub yes: bool,
70}
71
72/// Supported database providers
73#[derive(ValueEnum, Debug, Clone, Copy, Default)]
74pub enum DatabaseProvider {
75 #[default]
76 Postgresql,
77 Mysql,
78 Sqlite,
79}
80
81impl std::fmt::Display for DatabaseProvider {
82 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
83 match self {
84 DatabaseProvider::Postgresql => write!(f, "postgresql"),
85 DatabaseProvider::Mysql => write!(f, "mysql"),
86 DatabaseProvider::Sqlite => write!(f, "sqlite"),
87 }
88 }
89}
90
91// =============================================================================
92// Generate Command
93// =============================================================================
94
95/// Arguments for the `generate` command
96#[derive(Args, Debug)]
97pub struct GenerateArgs {
98 /// Path to schema file
99 #[arg(short, long)]
100 pub schema: Option<PathBuf>,
101
102 /// Output directory for generated code
103 #[arg(short, long)]
104 pub output: Option<PathBuf>,
105
106 /// Features to generate (e.g., serde, graphql)
107 #[arg(short, long, value_delimiter = ',')]
108 pub features: Vec<String>,
109
110 /// Watch for schema changes and regenerate
111 #[arg(short, long)]
112 pub watch: bool,
113}
114
115// =============================================================================
116// Validate Command
117// =============================================================================
118
119/// Arguments for the `validate` command
120#[derive(Args, Debug)]
121pub struct ValidateArgs {
122 /// Path to schema file
123 #[arg(short, long)]
124 pub schema: Option<PathBuf>,
125}
126
127// =============================================================================
128// Format Command
129// =============================================================================
130
131/// Arguments for the `format` command
132#[derive(Args, Debug)]
133pub struct FormatArgs {
134 /// Path to schema file
135 #[arg(short, long)]
136 pub schema: Option<PathBuf>,
137
138 /// Check formatting without writing changes
139 #[arg(short, long)]
140 pub check: bool,
141}
142
143// =============================================================================
144// Migrate Command
145// =============================================================================
146
147/// Arguments for the `migrate` command
148#[derive(Args, Debug)]
149pub struct MigrateArgs {
150 #[command(subcommand)]
151 pub command: MigrateSubcommand,
152}
153
154/// Migrate subcommands
155#[derive(Subcommand, Debug)]
156pub enum MigrateSubcommand {
157 /// Create and apply migrations during development
158 Dev(MigrateDevArgs),
159
160 /// Deploy pending migrations to production
161 Deploy,
162
163 /// Reset database and re-apply all migrations
164 Reset(MigrateResetArgs),
165
166 /// Show migration status
167 Status,
168
169 /// Resolve migration issues
170 Resolve(MigrateResolveArgs),
171
172 /// Generate migration diff without applying
173 Diff(MigrateDiffArgs),
174}
175
176/// Arguments for `migrate dev`
177#[derive(Args, Debug)]
178pub struct MigrateDevArgs {
179 /// Name for the migration
180 #[arg(short, long)]
181 pub name: Option<String>,
182
183 /// Create migration without applying
184 #[arg(long)]
185 pub create_only: bool,
186
187 /// Skip seed after migration
188 #[arg(long)]
189 pub skip_seed: bool,
190
191 /// Path to schema file
192 #[arg(short, long)]
193 pub schema: Option<PathBuf>,
194}
195
196/// Arguments for `migrate reset`
197#[derive(Args, Debug)]
198pub struct MigrateResetArgs {
199 /// Skip confirmation prompt
200 #[arg(short, long)]
201 pub force: bool,
202
203 /// Run seed after reset
204 #[arg(long)]
205 pub seed: bool,
206
207 /// Skip applying migrations (just reset)
208 #[arg(long)]
209 pub skip_migrations: bool,
210}
211
212/// Arguments for `migrate resolve`
213#[derive(Args, Debug)]
214pub struct MigrateResolveArgs {
215 /// Name of the migration to resolve
216 pub migration: String,
217
218 /// Mark migration as applied
219 #[arg(long)]
220 pub applied: bool,
221
222 /// Mark migration as rolled back
223 #[arg(long)]
224 pub rolled_back: bool,
225}
226
227/// Arguments for `migrate diff`
228#[derive(Args, Debug)]
229pub struct MigrateDiffArgs {
230 /// Path to schema file
231 #[arg(short, long)]
232 pub schema: Option<PathBuf>,
233
234 /// Output path for generated SQL
235 #[arg(short, long)]
236 pub output: Option<PathBuf>,
237
238 /// Compare against a specific migration
239 #[arg(long)]
240 pub from_migration: Option<String>,
241}
242
243// =============================================================================
244// Db Command
245// =============================================================================
246
247/// Arguments for the `db` command
248#[derive(Args, Debug)]
249pub struct DbArgs {
250 #[command(subcommand)]
251 pub command: DbSubcommand,
252}
253
254/// Db subcommands
255#[derive(Subcommand, Debug)]
256pub enum DbSubcommand {
257 /// Push schema to database without migrations
258 Push(DbPushArgs),
259
260 /// Introspect database and generate schema
261 Pull(DbPullArgs),
262
263 /// Seed database with initial data
264 Seed(DbSeedArgs),
265
266 /// Execute raw SQL
267 Execute(DbExecuteArgs),
268}
269
270/// Arguments for `db push`
271#[derive(Args, Debug)]
272pub struct DbPushArgs {
273 /// Path to schema file
274 #[arg(short, long)]
275 pub schema: Option<PathBuf>,
276
277 /// Accept data loss from destructive changes
278 #[arg(long)]
279 pub accept_data_loss: bool,
280
281 /// Skip confirmation prompts
282 #[arg(short, long)]
283 pub force: bool,
284
285 /// Reset database before push
286 #[arg(long)]
287 pub reset: bool,
288}
289
290/// Arguments for `db pull`
291#[derive(Args, Debug)]
292pub struct DbPullArgs {
293 /// Output path for generated schema
294 #[arg(short, long)]
295 pub output: Option<PathBuf>,
296
297 /// Overwrite existing schema without prompting
298 #[arg(short, long)]
299 pub force: bool,
300
301 /// Include views in introspection
302 #[arg(long)]
303 pub include_views: bool,
304}
305
306/// Arguments for `db seed`
307#[derive(Args, Debug)]
308pub struct DbSeedArgs {
309 /// Path to seed file
310 #[arg(short, long)]
311 pub seed_file: Option<PathBuf>,
312
313 /// Reset database before seeding
314 #[arg(long)]
315 pub reset: bool,
316
317 /// Environment to run seed for (development, staging, production)
318 #[arg(short, long, default_value = "development")]
319 pub environment: String,
320
321 /// Force seeding even if environment config says not to
322 #[arg(short, long)]
323 pub force: bool,
324}
325
326/// Arguments for `db execute`
327#[derive(Args, Debug)]
328pub struct DbExecuteArgs {
329 /// SQL to execute
330 #[arg(short, long)]
331 pub sql: Option<String>,
332
333 /// Path to SQL file
334 #[arg(short, long)]
335 pub file: Option<PathBuf>,
336
337 /// Read SQL from stdin
338 #[arg(long)]
339 pub stdin: bool,
340
341 /// Skip confirmation prompt
342 #[arg(short = 'y', long)]
343 pub force: bool,
344}