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 skill;
23pub mod swimlanes;
24pub mod system;
25mod transfer;
26pub mod users;
27
28#[cfg(test)]
29mod tests;
30
31use clap::Subcommand;
32
33#[derive(Debug, Subcommand)]
34pub enum RootCommand {
35 Skill(skill::SkillArgs),
37 System(system::SystemArgs),
39 Admin(Box<admin::AdminArgs>),
41 Rule(rules::RuleArgs),
43 Integration(integrations::IntegrationArgs),
45 Dependency(dependencies::DependencyArgs),
47 Attachment(attachments::AttachmentArgs),
49 Api(api::ApiArgs),
51
52 Auth(auth::AuthArgs),
54
55 Profile(profile::ProfileArgs),
57
58 User(users::UserArgs),
60
61 Board(boards::BoardArgs),
63
64 List(lists::ListArgs),
66
67 Card(Box<cards::CardArgs>),
69
70 Checklist(checklists::ChecklistArgs),
72
73 Comment(comments::CommentArgs),
75
76 CustomField(custom_fields::CustomFieldArgs),
78
79 Swimlane(swimlanes::SwimlaneArgs),
81}
82
83impl RootCommand {
84 pub fn supports_raw_output(&self) -> bool {
85 matches!(self, Self::Api(_))
86 || self.export_delivery().is_some_and(|d| d.is_stdout())
87 || matches!(self, Self::Attachment(args) if args.command.download_destination().is_some_and(|d| d.is_stdout()))
88 }
89
90 pub(crate) fn export_delivery(&self) -> Option<&exports::DeliveryArgs> {
91 match self {
92 Self::Board(a) => match &a.command {
93 boards::BoardCommand::Export(e) => Some(&e.delivery),
94 boards::BoardCommand::ExportAll(e) => Some(&e.delivery),
95 boards::BoardCommand::Chart(a) => a.delivery(),
96 _ => None,
97 },
98 Self::Card(a) => {
99 if let cards::CardCommand::Export(e) = &a.command {
100 Some(&e.delivery)
101 } else {
102 None
103 }
104 }
105 Self::Attachment(a) => {
106 if let attachments::AttachmentCommand::Export(e) = &a.command {
107 Some(&e.delivery)
108 } else {
109 None
110 }
111 }
112 _ => None,
113 }
114 }
115 pub(crate) fn validate_input(&self) -> Result<(), crate::error::AppError> {
116 if let Self::Board(a) = self {
117 if let boards::BoardCommand::Import(args) = &a.command {
118 args.validate()?;
119 }
120 if let boards::BoardCommand::ImportTrello(args) = &a.command {
121 args.validate()?;
122 }
123 }
124 if let Self::Board(a) = self {
125 if let boards::BoardCommand::Export(e) = &a.command {
126 e.validate()?;
127 }
128 }
129 if let Some(delivery) = self.export_delivery() {
130 delivery.validate()?;
131 }
132 Ok(())
133 }
134 pub fn validate_output(
135 &self,
136 format: crate::output::OutputFormat,
137 ) -> Result<(), crate::error::AppError> {
138 self.validate_input()?;
139 if let Some(delivery) = self.export_delivery() {
140 delivery.validate_output(format)?;
141 }
142 if let Self::Attachment(args) = self {
143 args.command.validate_input()?;
144 if let Some(destination) = args.command.download_destination() {
145 destination.validate_output(format)?;
146 }
147 }
148 if format == crate::output::OutputFormat::Raw && !self.supports_raw_output() {
149 return Err(crate::error::AppError::invalid_input(
150 "--output raw requires api request, an export, or an attachment download with --destination -",
151 ));
152 }
153 Ok(())
154 }
155}