1pub mod admin;
2pub mod api;
3pub mod attachments;
4pub mod auth;
5pub(crate) mod authenticated;
6pub mod boards;
7pub mod cards;
8pub mod checklist_items;
9pub mod checklists;
10pub(crate) mod client_error;
11pub mod comments;
12pub(crate) mod credential_ops;
13pub mod custom_field_items;
14pub mod custom_fields;
15pub mod dependencies;
16pub(crate) mod exports;
17pub(crate) mod imports;
18pub mod integrations;
19pub mod lists;
20pub mod profile;
21pub mod rules;
22pub mod self_management;
23pub mod skill;
24pub mod swimlanes;
25pub mod system;
26mod transfer;
27pub mod users;
28
29#[cfg(test)]
30mod tests;
31
32use clap::Subcommand;
33
34#[derive(Debug, Subcommand)]
35pub enum RootCommand {
36 #[command(name = "self")]
38 SelfManagement(self_management::SelfArgs),
39 Skill(skill::SkillArgs),
41 System(system::SystemArgs),
43 Admin(Box<admin::AdminArgs>),
45 Rule(rules::RuleArgs),
47 Integration(integrations::IntegrationArgs),
49 Dependency(dependencies::DependencyArgs),
51 Attachment(attachments::AttachmentArgs),
53 Api(api::ApiArgs),
55
56 Auth(auth::AuthArgs),
58
59 Profile(profile::ProfileArgs),
61
62 User(users::UserArgs),
64
65 Board(boards::BoardArgs),
67
68 List(lists::ListArgs),
70
71 Card(Box<cards::CardArgs>),
73
74 Checklist(checklists::ChecklistArgs),
76
77 Comment(comments::CommentArgs),
79
80 CustomField(custom_fields::CustomFieldArgs),
82
83 Swimlane(swimlanes::SwimlaneArgs),
85}
86
87impl RootCommand {
88 pub fn supports_raw_output(&self) -> bool {
89 matches!(self, Self::Api(_))
90 || self.export_delivery().is_some_and(|d| d.is_stdout())
91 || matches!(self, Self::Attachment(args) if args.command.download_destination().is_some_and(|d| d.is_stdout()))
92 }
93
94 pub(crate) fn export_delivery(&self) -> Option<&exports::DeliveryArgs> {
95 match self {
96 Self::Board(a) => match &a.command {
97 boards::BoardCommand::Export(e) => Some(&e.delivery),
98 boards::BoardCommand::ExportAll(e) => Some(&e.delivery),
99 boards::BoardCommand::Chart(a) => a.delivery(),
100 _ => None,
101 },
102 Self::Card(a) => {
103 if let cards::CardCommand::Export(e) = &a.command {
104 Some(&e.delivery)
105 } else {
106 None
107 }
108 }
109 Self::Attachment(a) => {
110 if let attachments::AttachmentCommand::Export(e) = &a.command {
111 Some(&e.delivery)
112 } else {
113 None
114 }
115 }
116 _ => None,
117 }
118 }
119 pub(crate) fn validate_input(&self) -> Result<(), crate::error::AppError> {
120 if let Self::Board(a) = self {
121 if let boards::BoardCommand::Import(args) = &a.command {
122 args.validate()?;
123 }
124 if let boards::BoardCommand::ImportTrello(args) = &a.command {
125 args.validate()?;
126 }
127 }
128 if let Self::Board(a) = self {
129 if let boards::BoardCommand::Export(e) = &a.command {
130 e.validate()?;
131 }
132 }
133 if let Some(delivery) = self.export_delivery() {
134 delivery.validate()?;
135 }
136 Ok(())
137 }
138 pub fn validate_output(
139 &self,
140 format: crate::output::OutputFormat,
141 ) -> Result<(), crate::error::AppError> {
142 self.validate_input()?;
143 if let Some(delivery) = self.export_delivery() {
144 delivery.validate_output(format)?;
145 }
146 if let Self::Attachment(args) = self {
147 args.command.validate_input()?;
148 if let Some(destination) = args.command.download_destination() {
149 destination.validate_output(format)?;
150 }
151 }
152 if format == crate::output::OutputFormat::Raw && !self.supports_raw_output() {
153 return Err(crate::error::AppError::invalid_input(
154 "--output raw requires api request, an export, or an attachment download with --destination -",
155 ));
156 }
157 Ok(())
158 }
159}