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 Saas,
114 Worker,
116 List,
118}
119
120#[derive(Parser, Debug)]
121pub struct AddArgs {
122 #[arg(value_enum)]
124 pub feature: AddFeature,
125
126 #[arg(short, long, default_value = ".")]
128 pub path: String,
129
130 #[arg(long, default_value = "false")]
132 pub force: bool,
133
134 #[arg(long, default_value = "false")]
136 pub wire: bool,
137}
138
139#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
140pub enum AddFeature {
141 Auth,
142 Database,
143 Openapi,
144 Validation,
145 Cache,
146 Sessions,
147 Jobs,
148 Websocket,
149 Metrics,
150 Email,
151}
152
153#[derive(Parser, Debug)]
154pub struct DoctorArgs {
155 #[arg(short, long, default_value = ".")]
157 pub path: String,
158
159 #[arg(long, default_value = "false")]
161 pub fix: bool,
162}
163
164#[derive(Parser, Debug)]
165pub struct SetupArgs {
166 #[arg(value_enum, default_value = "vue")]
168 pub framework: Framework,
169
170 #[arg(short, long, default_value = "shadcn")]
172 pub style: Style,
173
174 #[arg(long, default_value = "false")]
176 pub no_tailwind: bool,
177
178 #[arg(long, default_value = "false")]
180 pub no_components: bool,
181}
182
183#[derive(Parser, Debug)]
184pub struct DevArgs {
185 #[arg(short, long, default_value = ".")]
187 pub path: String,
188
189 #[arg(long, default_value = "false")]
191 pub no_env: bool,
192
193 #[arg(long, default_value = "false")]
195 pub fix_env: bool,
196
197 #[arg(long, default_value = "false")]
199 pub no_migrate: bool,
200
201 #[arg(trailing_var_arg = true)]
203 pub args: Vec<String>,
204}
205
206#[derive(Parser, Debug)]
207pub struct MigrateArgs {
208 #[arg(value_name = "ACTION", default_value = "up")]
210 pub action: String,
211
212 #[arg(short, long, default_value = ".")]
214 pub path: String,
215
216 #[arg(long, value_enum, default_value = "auto")]
218 pub backend: MigrateBackend,
219
220 #[arg(long, default_value = "false")]
222 pub no_env: bool,
223
224 #[arg(long, default_value = "false")]
226 pub fix_env: bool,
227
228 #[arg(trailing_var_arg = true)]
230 pub args: Vec<String>,
231}
232
233#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
234pub enum MigrateBackend {
235 Auto,
237 SeaOrm,
239}
240
241#[derive(Parser, Debug)]
242pub struct InitArgs {
243 #[arg(short, long, default_value = "./src")]
245 pub src: String,
246
247 #[arg(short, long)]
249 pub name: Option<String>,
250
251 #[arg(long, default_value = "false")]
253 pub force: bool,
254
255 #[arg(long, default_value = "false")]
257 pub no_database: bool,
258
259 #[arg(long, default_value = "false")]
261 pub no_migrations: bool,
262
263 #[arg(long, default_value = "true")]
265 pub env_example: bool,
266
267 #[arg(long, default_value = "false")]
269 pub minimal: bool,
270}
271
272#[derive(Parser, Debug)]
273pub struct ResourceArgs {
274 #[arg(value_name = "NAME")]
276 pub name: String,
277
278 #[arg(short, long, default_value = ".")]
280 pub path: String,
281
282 #[arg(long, default_value = "false")]
284 pub wire: bool,
285
286 #[arg(long, default_value = "true")]
288 pub with_tests: bool,
289
290 #[arg(long, default_value = "false")]
292 pub db: bool,
293
294 #[arg(long, default_value = "false")]
296 pub repo: bool,
297
298 #[arg(long, default_value = "false")]
300 pub repo_tests: bool,
301
302 #[arg(long, default_value = "false")]
304 pub service: bool,
305
306 #[arg(long, value_enum, default_value = "int")]
308 pub id_type: ResourceIdType,
309
310 #[arg(long, default_value = "false")]
312 pub add_uuid: bool,
313
314 #[arg(long, default_value = "false")]
316 pub paginate: bool,
317
318 #[arg(long, default_value = "false")]
320 pub search: bool,
321
322 #[arg(long, value_enum, default_value = "auto")]
324 pub db_backend: DbBackend,
325}
326
327#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
328pub enum ResourceIdType {
329 Int,
331 Uuid,
333}
334
335#[derive(ValueEnum, Debug, Copy, Clone, Eq, PartialEq)]
336pub enum DbBackend {
337 Auto,
339 SeaOrm,
341}
342
343#[derive(Parser, Debug)]
344pub struct BackendArgs {
345 #[arg(value_enum)]
347 pub preset: BackendPreset,
348
349 #[arg(short, long, default_value = "my_app")]
351 pub name: String,
352
353 #[arg(short, long, default_value = "./src")]
355 pub output: String,
356
357 #[arg(long, default_value = "./migration/src")]
359 pub migrations_output: String,
360
361 #[arg(long, default_value = "false")]
363 pub force: bool,
364
365 #[arg(long, default_value = "postgres", value_parser = ["postgres", "sqlite"])]
367 pub database: String,
368}
369
370#[derive(ValueEnum, Clone, Debug, PartialEq)]
371pub enum BackendPreset {
372 B2c,
374 B2b,
376}
377
378#[derive(Parser, Debug)]
379pub struct GenerateArgs {
380 #[arg(value_enum)]
382 pub module: Module,
383
384 #[arg(short, long, default_value = "vue")]
386 pub framework: Framework,
387
388 #[arg(short, long, default_value = "shadcn")]
390 pub style: Style,
391
392 #[arg(short, long, default_value = "./src/components/tideway")]
394 pub output: String,
395
396 #[arg(long, default_value = "http://localhost:3000")]
398 pub api_base: String,
399
400 #[arg(long, default_value = "false")]
402 pub force: bool,
403
404 #[arg(long, default_value = "false")]
406 pub no_shared: bool,
407
408 #[arg(long, default_value = "false")]
410 pub with_views: bool,
411
412 #[arg(long, default_value = "./src/views")]
414 pub views_output: String,
415}
416
417#[derive(ValueEnum, Clone, Debug, PartialEq)]
418pub enum Module {
419 Auth,
421 Billing,
423 Organizations,
425 Admin,
427 All,
429}
430
431#[derive(ValueEnum, Clone, Debug, PartialEq)]
432pub enum Framework {
433 Vue,
435 }
437
438#[derive(ValueEnum, Clone, Debug, PartialEq)]
439pub enum Style {
440 Shadcn,
442 Tailwind,
444 Unstyled,
446}
447
448impl std::fmt::Display for Module {
449 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
450 match self {
451 Module::Auth => write!(f, "auth"),
452 Module::Billing => write!(f, "billing"),
453 Module::Organizations => write!(f, "organizations"),
454 Module::Admin => write!(f, "admin"),
455 Module::All => write!(f, "all"),
456 }
457 }
458}
459
460impl std::fmt::Display for Framework {
461 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
462 match self {
463 Framework::Vue => write!(f, "vue"),
464 }
465 }
466}
467
468impl std::fmt::Display for Style {
469 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
470 match self {
471 Style::Shadcn => write!(f, "shadcn"),
472 Style::Tailwind => write!(f, "tailwind"),
473 Style::Unstyled => write!(f, "unstyled"),
474 }
475 }
476}
477
478impl std::fmt::Display for BackendPreset {
479 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
480 match self {
481 BackendPreset::B2c => write!(f, "b2c"),
482 BackendPreset::B2b => write!(f, "b2b"),
483 }
484 }
485}
486
487impl std::fmt::Display for AddFeature {
488 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
489 let name = match self {
490 AddFeature::Auth => "auth",
491 AddFeature::Database => "database",
492 AddFeature::Openapi => "openapi",
493 AddFeature::Validation => "validation",
494 AddFeature::Cache => "cache",
495 AddFeature::Sessions => "sessions",
496 AddFeature::Jobs => "jobs",
497 AddFeature::Websocket => "websocket",
498 AddFeature::Metrics => "metrics",
499 AddFeature::Email => "email",
500 };
501 write!(f, "{}", name)
502 }
503}