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
179/// Arguments for `migrate dev`
180#[derive(Args, Debug)]
181pub struct MigrateDevArgs {
182 /// Name for the migration
183 #[arg(short, long)]
184 pub name: Option<String>,
185
186 /// Create migration without applying
187 #[arg(long)]
188 pub create_only: bool,
189
190 /// Skip seed after migration
191 #[arg(long)]
192 pub skip_seed: bool,
193
194 /// Path to schema file
195 #[arg(short, long)]
196 pub schema: Option<PathBuf>,
197}
198
199/// Arguments for `migrate reset`
200#[derive(Args, Debug)]
201pub struct MigrateResetArgs {
202 /// Skip confirmation prompt
203 #[arg(short, long)]
204 pub force: bool,
205
206 /// Run seed after reset
207 #[arg(long)]
208 pub seed: bool,
209
210 /// Skip applying migrations (just reset)
211 #[arg(long)]
212 pub skip_migrations: bool,
213}
214
215/// Arguments for `migrate resolve`
216#[derive(Args, Debug)]
217pub struct MigrateResolveArgs {
218 /// Name of the migration to resolve
219 pub migration: String,
220
221 /// Mark migration as applied
222 #[arg(long)]
223 pub applied: bool,
224
225 /// Mark migration as rolled back
226 #[arg(long)]
227 pub rolled_back: bool,
228}
229
230/// Arguments for `migrate diff`
231#[derive(Args, Debug)]
232pub struct MigrateDiffArgs {
233 /// Path to schema file
234 #[arg(short, long)]
235 pub schema: Option<PathBuf>,
236
237 /// Output path for generated SQL
238 #[arg(short, long)]
239 pub output: Option<PathBuf>,
240
241 /// Compare against a specific migration
242 #[arg(long)]
243 pub from_migration: Option<String>,
244}
245
246// =============================================================================
247// Db Command
248// =============================================================================
249
250/// Arguments for the `db` command
251#[derive(Args, Debug)]
252pub struct DbArgs {
253 #[command(subcommand)]
254 pub command: DbSubcommand,
255}
256
257/// Db subcommands
258#[derive(Subcommand, Debug)]
259pub enum DbSubcommand {
260 /// Push schema to database without migrations
261 Push(DbPushArgs),
262
263 /// Introspect database and generate schema
264 Pull(DbPullArgs),
265
266 /// Seed database with initial data
267 Seed(DbSeedArgs),
268
269 /// Execute raw SQL
270 Execute(DbExecuteArgs),
271}
272
273/// Arguments for `db push`
274#[derive(Args, Debug)]
275pub struct DbPushArgs {
276 /// Path to schema file
277 #[arg(short, long)]
278 pub schema: Option<PathBuf>,
279
280 /// Accept data loss from destructive changes
281 #[arg(long)]
282 pub accept_data_loss: bool,
283
284 /// Skip confirmation prompts
285 #[arg(short, long)]
286 pub force: bool,
287
288 /// Reset database before push
289 #[arg(long)]
290 pub reset: bool,
291}
292
293/// Arguments for `db pull`
294#[derive(Args, Debug)]
295pub struct DbPullArgs {
296 /// Output path for generated schema
297 #[arg(short, long)]
298 pub output: Option<PathBuf>,
299
300 /// Overwrite existing schema without prompting
301 #[arg(short, long)]
302 pub force: bool,
303
304 /// Include views in introspection
305 #[arg(long)]
306 pub include_views: bool,
307
308 /// Include materialized views in introspection
309 #[arg(long)]
310 pub include_materialized_views: bool,
311
312 /// Schema/namespace to introspect (default: public for PostgreSQL, dbo for MSSQL)
313 #[arg(long)]
314 pub schema: Option<String>,
315
316 /// Filter tables by pattern (glob-style, e.g., "user*")
317 #[arg(long)]
318 pub tables: Option<String>,
319
320 /// Exclude tables by pattern (glob-style, e.g., "_prisma*")
321 #[arg(long)]
322 pub exclude: Option<String>,
323
324 /// Print schema to stdout instead of writing to file
325 #[arg(long)]
326 pub print: bool,
327
328 /// Output format
329 #[arg(long, default_value = "prax")]
330 pub format: OutputFormat,
331
332 /// Number of documents to sample for MongoDB schema inference
333 #[arg(long, default_value = "100")]
334 pub sample_size: usize,
335
336 /// Include column comments in schema
337 #[arg(long)]
338 pub comments: bool,
339}
340
341/// Output format for schema introspection
342#[derive(ValueEnum, Debug, Clone, Copy, Default)]
343pub enum OutputFormat {
344 /// Prax schema format (.prax)
345 #[default]
346 Prax,
347 /// JSON format
348 Json,
349 /// SQL DDL format
350 Sql,
351}
352
353/// Arguments for `db seed`
354#[derive(Args, Debug)]
355pub struct DbSeedArgs {
356 /// Path to seed file
357 #[arg(short, long)]
358 pub seed_file: Option<PathBuf>,
359
360 /// Reset database before seeding
361 #[arg(long)]
362 pub reset: bool,
363
364 /// Environment to run seed for (development, staging, production)
365 #[arg(short, long, default_value = "development")]
366 pub environment: String,
367
368 /// Force seeding even if environment config says not to
369 #[arg(short, long)]
370 pub force: bool,
371}
372
373/// Arguments for `db execute`
374#[derive(Args, Debug)]
375pub struct DbExecuteArgs {
376 /// SQL to execute
377 #[arg(short, long)]
378 pub sql: Option<String>,
379
380 /// Path to SQL file
381 #[arg(short, long)]
382 pub file: Option<PathBuf>,
383
384 /// Read SQL from stdin
385 #[arg(long)]
386 pub stdin: bool,
387
388 /// Skip confirmation prompt
389 #[arg(short = 'y', long)]
390 pub force: bool,
391}
392
393// =============================================================================
394// Import Command
395// =============================================================================
396
397/// Arguments for the `import` command
398#[derive(Args, Debug)]
399pub struct ImportArgs {
400 /// Source ORM to import from
401 #[arg(long, value_enum)]
402 pub from: ImportSource,
403
404 /// Input schema file path
405 #[arg(short, long)]
406 pub input: PathBuf,
407
408 /// Output Prax schema file path
409 #[arg(short, long)]
410 pub output: Option<PathBuf>,
411
412 /// Database provider for the imported schema
413 #[arg(short = 'P', long)]
414 pub provider: Option<DatabaseProvider>,
415
416 /// Database connection URL for the imported schema
417 #[arg(short, long)]
418 pub url: Option<String>,
419
420 /// Print to stdout instead of writing to file
421 #[arg(long)]
422 pub print: bool,
423
424 /// Overwrite existing output file without prompting
425 #[arg(short, long)]
426 pub force: bool,
427}
428
429/// Source ORM for import
430#[derive(ValueEnum, Debug, Clone, Copy)]
431pub enum ImportSource {
432 /// Prisma schema (.prisma files)
433 Prisma,
434 /// Diesel schema (schema.rs files with table! macros)
435 Diesel,
436 /// SeaORM entity (entity files with DeriveEntityModel)
437 SeaOrm,
438}