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