1use clap::{Parser, Subcommand, ValueEnum};
4
5#[derive(Parser)]
6#[command(name = "tideway")]
7#[command(author = "JD")]
8#[command(version)]
9#[command(about = "Scaffold Tideway apps and generate components", long_about = None)]
10pub struct Cli {
11 #[arg(long, global = true, default_value = "false")]
13 pub json: bool,
14
15 #[arg(long, global = true, default_value = "false")]
17 pub plan: bool,
18
19 #[command(subcommand)]
20 pub command: Commands,
21}
22
23#[derive(Subcommand)]
24pub enum Commands {
25 New(NewArgs),
27
28 Doctor(DoctorArgs),
30
31 Generate(GenerateArgs),
33
34 Backend(BackendArgs),
36
37 Add(AddArgs),
39
40 Init(InitArgs),
42
43 Resource(ResourceArgs),
45
46 Setup(SetupArgs),
48
49 Dev(DevArgs),
51
52 Migrate(MigrateArgs),
54
55 Templates,
57}
58
59#[derive(Parser, Debug)]
60pub struct NewArgs {
61 #[arg(value_name = "NAME")]
63 pub name: Option<String>,
64
65 #[arg(long, value_enum)]
67 pub preset: Option<NewPreset>,
68
69 #[arg(long, value_delimiter = ',')]
71 pub features: Vec<String>,
72
73 #[arg(long, default_value = "false")]
75 pub with_config: bool,
76
77 #[arg(long, default_value = "false")]
79 pub with_docker: bool,
80
81 #[arg(long, default_value = "false")]
83 pub with_ci: bool,
84
85 #[arg(long, default_value = "false")]
87 pub no_prompt: bool,
88
89 #[arg(long, default_value = "true")]
91 pub summary: bool,
92
93 #[arg(long, default_value = "false")]
95 pub with_env: bool,
96
97 #[arg(short, long)]
99 pub path: Option<String>,
100
101 #[arg(long, default_value = "false")]
103 pub force: bool,
104}
105
106#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
107pub enum NewPreset {
108 Minimal,
110 Api,
112 List,
114}
115
116#[derive(Parser, Debug)]
117pub struct AddArgs {
118 #[arg(value_enum)]
120 pub feature: AddFeature,
121
122 #[arg(short, long, default_value = ".")]
124 pub path: String,
125
126 #[arg(long, default_value = "false")]
128 pub force: bool,
129
130 #[arg(long, default_value = "false")]
132 pub wire: bool,
133}
134
135#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
136pub enum AddFeature {
137 Auth,
138 Database,
139 Openapi,
140 Validation,
141 Cache,
142 Sessions,
143 Jobs,
144 Websocket,
145 Metrics,
146 Email,
147}
148
149#[derive(Parser, Debug)]
150pub struct DoctorArgs {
151 #[arg(short, long, default_value = ".")]
153 pub path: String,
154
155 #[arg(long, default_value = "false")]
157 pub fix: bool,
158}
159
160#[derive(Parser, Debug)]
161pub struct SetupArgs {
162 #[arg(value_enum, default_value = "vue")]
164 pub framework: Framework,
165
166 #[arg(short, long, default_value = "shadcn")]
168 pub style: Style,
169
170 #[arg(long, default_value = "false")]
172 pub no_tailwind: bool,
173
174 #[arg(long, default_value = "false")]
176 pub no_components: bool,
177}
178
179#[derive(Parser, Debug)]
180pub struct DevArgs {
181 #[arg(short, long, default_value = ".")]
183 pub path: String,
184
185 #[arg(long, default_value = "false")]
187 pub no_env: bool,
188
189 #[arg(long, default_value = "false")]
191 pub fix_env: bool,
192
193 #[arg(long, default_value = "false")]
195 pub no_migrate: bool,
196
197 #[arg(trailing_var_arg = true)]
199 pub args: Vec<String>,
200}
201
202#[derive(Parser, Debug)]
203pub struct MigrateArgs {
204 #[arg(value_name = "ACTION", default_value = "up")]
206 pub action: String,
207
208 #[arg(short, long, default_value = ".")]
210 pub path: String,
211
212 #[arg(long, value_enum, default_value = "auto")]
214 pub backend: MigrateBackend,
215
216 #[arg(long, default_value = "false")]
218 pub no_env: bool,
219
220 #[arg(long, default_value = "false")]
222 pub fix_env: bool,
223
224 #[arg(trailing_var_arg = true)]
226 pub args: Vec<String>,
227}
228
229#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
230pub enum MigrateBackend {
231 Auto,
233 SeaOrm,
235}
236
237#[derive(Parser, Debug)]
238pub struct InitArgs {
239 #[arg(short, long, default_value = "./src")]
241 pub src: String,
242
243 #[arg(short, long)]
245 pub name: Option<String>,
246
247 #[arg(long, default_value = "false")]
249 pub force: bool,
250
251 #[arg(long, default_value = "false")]
253 pub no_database: bool,
254
255 #[arg(long, default_value = "false")]
257 pub no_migrations: bool,
258
259 #[arg(long, default_value = "true")]
261 pub env_example: bool,
262
263 #[arg(long, default_value = "false")]
265 pub minimal: bool,
266}
267
268#[derive(Parser, Debug)]
269pub struct ResourceArgs {
270 #[arg(value_name = "NAME")]
272 pub name: String,
273
274 #[arg(short, long, default_value = ".")]
276 pub path: String,
277
278 #[arg(long, default_value = "false")]
280 pub wire: bool,
281
282 #[arg(long, default_value = "true")]
284 pub with_tests: bool,
285
286 #[arg(long, default_value = "false")]
288 pub db: bool,
289
290 #[arg(long, default_value = "false")]
292 pub repo: bool,
293
294 #[arg(long, default_value = "false")]
296 pub repo_tests: bool,
297
298 #[arg(long, default_value = "false")]
300 pub service: bool,
301
302 #[arg(long, value_enum, default_value = "int")]
304 pub id_type: ResourceIdType,
305
306 #[arg(long, default_value = "false")]
308 pub add_uuid: bool,
309
310 #[arg(long, default_value = "false")]
312 pub paginate: bool,
313
314 #[arg(long, default_value = "false")]
316 pub search: bool,
317
318 #[arg(long, value_enum, default_value = "auto")]
320 pub db_backend: DbBackend,
321}
322
323#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
324pub enum ResourceIdType {
325 Int,
327 Uuid,
329}
330
331#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
332pub enum DbBackend {
333 Auto,
335 SeaOrm,
337}
338
339#[derive(Parser, Debug)]
340pub struct BackendArgs {
341 #[arg(value_enum)]
343 pub preset: BackendPreset,
344
345 #[arg(short, long, default_value = "my_app")]
347 pub name: String,
348
349 #[arg(short, long, default_value = "./src")]
351 pub output: String,
352
353 #[arg(long, default_value = "./migration/src")]
355 pub migrations_output: String,
356
357 #[arg(long, default_value = "false")]
359 pub force: bool,
360
361 #[arg(long, default_value = "postgres", value_parser = ["postgres", "sqlite"])]
363 pub database: String,
364}
365
366#[derive(ValueEnum, Clone, Debug, PartialEq)]
367pub enum BackendPreset {
368 B2c,
370 B2b,
372}
373
374#[derive(Parser, Debug)]
375pub struct GenerateArgs {
376 #[arg(value_enum)]
378 pub module: Module,
379
380 #[arg(short, long, default_value = "vue")]
382 pub framework: Framework,
383
384 #[arg(short, long, default_value = "shadcn")]
386 pub style: Style,
387
388 #[arg(short, long, default_value = "./src/components/tideway")]
390 pub output: String,
391
392 #[arg(long, default_value = "http://localhost:3000")]
394 pub api_base: String,
395
396 #[arg(long, default_value = "false")]
398 pub force: bool,
399
400 #[arg(long, default_value = "false")]
402 pub no_shared: bool,
403
404 #[arg(long, default_value = "false")]
406 pub with_views: bool,
407
408 #[arg(long, default_value = "./src/views")]
410 pub views_output: String,
411}
412
413#[derive(ValueEnum, Clone, Debug, PartialEq)]
414pub enum Module {
415 Auth,
417 Billing,
419 Organizations,
421 Admin,
423 All,
425}
426
427#[derive(ValueEnum, Clone, Debug, PartialEq)]
428pub enum Framework {
429 Vue,
431 }
433
434#[derive(ValueEnum, Clone, Debug, PartialEq)]
435pub enum Style {
436 Shadcn,
438 Tailwind,
440 Unstyled,
442}
443
444impl std::fmt::Display for Module {
445 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
446 match self {
447 Module::Auth => write!(f, "auth"),
448 Module::Billing => write!(f, "billing"),
449 Module::Organizations => write!(f, "organizations"),
450 Module::Admin => write!(f, "admin"),
451 Module::All => write!(f, "all"),
452 }
453 }
454}
455
456impl std::fmt::Display for Framework {
457 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
458 match self {
459 Framework::Vue => write!(f, "vue"),
460 }
461 }
462}
463
464impl std::fmt::Display for Style {
465 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
466 match self {
467 Style::Shadcn => write!(f, "shadcn"),
468 Style::Tailwind => write!(f, "tailwind"),
469 Style::Unstyled => write!(f, "unstyled"),
470 }
471 }
472}
473
474impl std::fmt::Display for BackendPreset {
475 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
476 match self {
477 BackendPreset::B2c => write!(f, "b2c"),
478 BackendPreset::B2b => write!(f, "b2b"),
479 }
480 }
481}
482
483impl std::fmt::Display for AddFeature {
484 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
485 let name = match self {
486 AddFeature::Auth => "auth",
487 AddFeature::Database => "database",
488 AddFeature::Openapi => "openapi",
489 AddFeature::Validation => "validation",
490 AddFeature::Cache => "cache",
491 AddFeature::Sessions => "sessions",
492 AddFeature::Jobs => "jobs",
493 AddFeature::Websocket => "websocket",
494 AddFeature::Metrics => "metrics",
495 AddFeature::Email => "email",
496 };
497 write!(f, "{}", name)
498 }
499}