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 /// Import schema from Prisma or Diesel
41 Import(ImportArgs),
42
43 /// Display version information
44 Version,
45}
46
47// =============================================================================
48// Init Command
49// =============================================================================
50
51/// Arguments for the `init` command
52#[derive(Args, Debug)]
53pub struct InitArgs {
54 /// Path to initialize the project (defaults to current directory)
55 #[arg(default_value = ".")]
56 pub path: PathBuf,
57
58 /// Database provider to use
59 #[arg(short, long, default_value = "postgresql")]
60 pub provider: DatabaseProvider,
61
62 /// Database connection URL
63 #[arg(short, long)]
64 pub url: Option<String>,
65
66 /// Skip generating example schema
67 #[arg(long)]
68 pub no_example: bool,
69
70 /// Accept all defaults without prompting
71 #[arg(short, long)]
72 pub yes: bool,
73}
74
75/// Supported database providers
76#[derive(ValueEnum, Debug, Clone, Copy, Default)]
77pub enum DatabaseProvider {
78 #[default]
79 Postgresql,
80 Mysql,
81 Sqlite,
82}
83
84impl std::fmt::Display for DatabaseProvider {
85 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86 match self {
87 DatabaseProvider::Postgresql => write!(f, "postgresql"),
88 DatabaseProvider::Mysql => write!(f, "mysql"),
89 DatabaseProvider::Sqlite => write!(f, "sqlite"),
90 }
91 }
92}
93
94// =============================================================================
95// Generate Command
96// =============================================================================
97
98/// Arguments for the `generate` command
99#[derive(Args, Debug)]
100pub struct GenerateArgs {
101 /// Path to schema file
102 #[arg(short, long)]
103 pub schema: Option<PathBuf>,
104
105 /// Output directory for generated code
106 #[arg(short, long)]
107 pub output: Option<PathBuf>,
108
109 /// Features to generate (e.g., serde, graphql)
110 #[arg(short, long, value_delimiter = ',')]
111 pub features: Vec<String>,
112
113 /// Watch for schema changes and regenerate
114 #[arg(short, long)]
115 pub watch: bool,
116}
117
118// =============================================================================
119// Validate Command
120// =============================================================================
121
122/// Arguments for the `validate` command
123#[derive(Args, Debug)]
124pub struct ValidateArgs {
125 /// Path to schema file
126 #[arg(short, long)]
127 pub schema: Option<PathBuf>,
128}
129
130// =============================================================================
131// Format Command
132// =============================================================================
133
134/// Arguments for the `format` command
135#[derive(Args, Debug)]
136pub struct FormatArgs {
137 /// Path to schema file
138 #[arg(short, long)]
139 pub schema: Option<PathBuf>,
140
141 /// Check formatting without writing changes
142 #[arg(short, long)]
143 pub check: bool,
144}
145
146// =============================================================================
147// Migrate Command
148// =============================================================================
149
150/// Arguments for the `migrate` command
151#[derive(Args, Debug)]
152pub struct MigrateArgs {
153 #[command(subcommand)]
154 pub command: MigrateSubcommand,
155}
156
157/// Migrate subcommands
158#[derive(Subcommand, Debug)]
159pub enum MigrateSubcommand {
160 /// Create and apply migrations during development
161 Dev(MigrateDevArgs),
162
163 /// Deploy pending migrations to production
164 Deploy,
165
166 /// Reset database and re-apply all migrations
167 Reset(MigrateResetArgs),
168
169 /// Show migration status
170 Status,
171
172 /// Resolve migration issues
173 Resolve(MigrateResolveArgs),
174
175 /// Generate migration diff without applying
176 Diff(MigrateDiffArgs),
177
178 /// Rollback the last applied migration
179 Rollback(MigrateRollbackArgs),
180
181 /// View migration history
182 History(MigrateHistoryArgs),
183}
184
185/// Arguments for `migrate dev`
186#[derive(Args, Debug)]
187pub struct MigrateDevArgs {
188 /// Name for the migration
189 #[arg(short, long)]
190 pub name: Option<String>,
191
192 /// Create migration without applying
193 #[arg(long)]
194 pub create_only: bool,
195
196 /// Skip seed after migration
197 #[arg(long)]
198 pub skip_seed: bool,
199
200 /// Path to schema file
201 #[arg(short, long)]
202 pub schema: Option<PathBuf>,
203}
204
205/// Arguments for `migrate reset`
206#[derive(Args, Debug)]
207pub struct MigrateResetArgs {
208 /// Skip confirmation prompt
209 #[arg(short, long)]
210 pub force: bool,
211
212 /// Run seed after reset
213 #[arg(long)]
214 pub seed: bool,
215
216 /// Skip applying migrations (just reset)
217 #[arg(long)]
218 pub skip_migrations: bool,
219}
220
221/// Arguments for `migrate resolve`
222#[derive(Args, Debug)]
223pub struct MigrateResolveArgs {
224 /// Name of the migration to resolve
225 pub migration: String,
226
227 /// Mark migration as applied
228 #[arg(long)]
229 pub applied: bool,
230
231 /// Mark migration as rolled back
232 #[arg(long)]
233 pub rolled_back: bool,
234}
235
236/// Arguments for `migrate diff`
237#[derive(Args, Debug)]
238pub struct MigrateDiffArgs {
239 /// Path to schema file
240 #[arg(short, long)]
241 pub schema: Option<PathBuf>,
242
243 /// Output path for generated SQL
244 #[arg(short, long)]
245 pub output: Option<PathBuf>,
246
247 /// Compare against a specific migration
248 #[arg(long)]
249 pub from_migration: Option<String>,
250}
251
252/// Arguments for `migrate rollback`
253#[derive(Args, Debug)]
254pub struct MigrateRollbackArgs {
255 /// Reason for rollback
256 #[arg(long)]
257 pub reason: Option<String>,
258
259 /// User performing the rollback
260 #[arg(long)]
261 pub user: Option<String>,
262
263 /// Rollback to a specific migration
264 #[arg(long)]
265 pub to: Option<String>,
266}
267
268/// Arguments for `migrate history`
269#[derive(Args, Debug)]
270pub struct MigrateHistoryArgs {
271 /// Show history for a specific migration
272 #[arg(long)]
273 pub migration: Option<String>,
274}
275
276// =============================================================================
277// Db Command
278// =============================================================================
279
280/// Arguments for the `db` command
281#[derive(Args, Debug)]
282pub struct DbArgs {
283 #[command(subcommand)]
284 pub command: DbSubcommand,
285}
286
287/// Db subcommands
288#[derive(Subcommand, Debug)]
289pub enum DbSubcommand {
290 /// Push schema to database without migrations
291 Push(DbPushArgs),
292
293 /// Introspect database and generate schema
294 Pull(DbPullArgs),
295
296 /// Seed database with initial data
297 Seed(DbSeedArgs),
298
299 /// Execute raw SQL
300 Execute(DbExecuteArgs),
301}
302
303/// Arguments for `db push`
304#[derive(Args, Debug)]
305pub struct DbPushArgs {
306 /// Path to schema file
307 #[arg(short, long)]
308 pub schema: Option<PathBuf>,
309
310 /// Accept data loss from destructive changes
311 #[arg(long)]
312 pub accept_data_loss: bool,
313
314 /// Skip confirmation prompts
315 #[arg(short, long)]
316 pub force: bool,
317
318 /// Reset database before push
319 #[arg(long)]
320 pub reset: bool,
321}
322
323/// Arguments for `db pull`
324#[derive(Args, Debug)]
325pub struct DbPullArgs {
326 /// Output path for generated schema
327 #[arg(short, long)]
328 pub output: Option<PathBuf>,
329
330 /// Overwrite existing schema without prompting
331 #[arg(short, long)]
332 pub force: bool,
333
334 /// Include views in introspection
335 #[arg(long)]
336 pub include_views: bool,
337
338 /// Include materialized views in introspection
339 #[arg(long)]
340 pub include_materialized_views: bool,
341
342 /// Schema/namespace to introspect (default: public for PostgreSQL, dbo for MSSQL)
343 #[arg(long)]
344 pub schema: Option<String>,
345
346 /// Filter tables by pattern (glob-style, e.g., "user*")
347 #[arg(long)]
348 pub tables: Option<String>,
349
350 /// Exclude tables by pattern (glob-style, e.g., "_prisma*")
351 #[arg(long)]
352 pub exclude: Option<String>,
353
354 /// Print schema to stdout instead of writing to file
355 #[arg(long)]
356 pub print: bool,
357
358 /// Output format
359 #[arg(long, default_value = "prax")]
360 pub format: OutputFormat,
361
362 /// Number of documents to sample for MongoDB schema inference
363 #[arg(long, default_value = "100")]
364 pub sample_size: usize,
365
366 /// Include column comments in schema
367 #[arg(long)]
368 pub comments: bool,
369}
370
371/// Output format for schema introspection
372#[derive(ValueEnum, Debug, Clone, Copy, Default)]
373pub enum OutputFormat {
374 /// Prax schema format (.prax)
375 #[default]
376 Prax,
377 /// JSON format
378 Json,
379 /// SQL DDL format
380 Sql,
381}
382
383/// Arguments for `db seed`
384#[derive(Args, Debug)]
385pub struct DbSeedArgs {
386 /// Path to seed file
387 #[arg(short, long)]
388 pub seed_file: Option<PathBuf>,
389
390 /// Reset database before seeding
391 #[arg(long)]
392 pub reset: bool,
393
394 /// Environment to run seed for (development, staging, production)
395 #[arg(short, long, default_value = "development")]
396 pub environment: String,
397
398 /// Force seeding even if environment config says not to
399 #[arg(short, long)]
400 pub force: bool,
401}
402
403/// Arguments for `db execute`
404#[derive(Args, Debug)]
405pub struct DbExecuteArgs {
406 /// SQL to execute
407 #[arg(short, long)]
408 pub sql: Option<String>,
409
410 /// Path to SQL file
411 #[arg(short, long)]
412 pub file: Option<PathBuf>,
413
414 /// Read SQL from stdin
415 #[arg(long)]
416 pub stdin: bool,
417
418 /// Skip confirmation prompt
419 #[arg(short = 'y', long)]
420 pub force: bool,
421}
422
423// =============================================================================
424// Import Command
425// =============================================================================
426
427/// Arguments for the `import` command
428#[derive(Args, Debug)]
429pub struct ImportArgs {
430 /// Source ORM to import from
431 #[arg(long, value_enum)]
432 pub from: ImportSource,
433
434 /// Input schema file path
435 #[arg(short, long)]
436 pub input: PathBuf,
437
438 /// Output Prax schema file path
439 #[arg(short, long)]
440 pub output: Option<PathBuf>,
441
442 /// Database provider for the imported schema
443 #[arg(short = 'P', long)]
444 pub provider: Option<DatabaseProvider>,
445
446 /// Database connection URL for the imported schema
447 #[arg(short, long)]
448 pub url: Option<String>,
449
450 /// Print to stdout instead of writing to file
451 #[arg(long)]
452 pub print: bool,
453
454 /// Overwrite existing output file without prompting
455 #[arg(short, long)]
456 pub force: bool,
457}
458
459/// Source ORM for import
460#[derive(ValueEnum, Debug, Clone, Copy)]
461pub enum ImportSource {
462 /// Prisma schema (.prisma files)
463 Prisma,
464 /// Diesel schema (schema.rs files with table! macros)
465 Diesel,
466 /// SeaORM entity (entity files with DeriveEntityModel)
467 SeaOrm,
468}