coman/cli/
manager.rs

1//! CLI commands for managing collections and endpoints
2//!
3//! This module provides the command-line interface for managing API collections,
4//! delegating the actual work to the core CollectionManager.
5
6use clap::Subcommand;
7use std::fmt;
8
9use crate::core::collection_manager::CollectionManager;
10use crate::core::errors::CollectionError;
11use crate::models::collection::Method;
12
13use super::request::RequestCommands;
14use super::request_data::RequestData;
15
16#[derive(Clone, Subcommand)]
17pub enum ManagerCommands {
18    #[clap(about = "List collections and endpoints")]
19    List {
20        #[clap(short = 'c', long = "col", default_value = "", required = false)]
21        col: String,
22
23        #[clap(short = 'e', long = "endpoint", default_value = "", required = false)]
24        endpoint: String,
25
26        #[clap(short = 'q', long = "quiet", default_value = "false")]
27        quiet: bool,
28
29        #[clap(short, long, default_value = "false")]
30        verbose: bool,
31    },
32    #[clap(about = "Update a collection or endpoint headers and body")]
33    Update {
34        collection: String,
35
36        #[clap(short = 'e', long, default_value = "", required = false)]
37        endpoint: String,
38
39        #[clap(short = 'u', long, default_value = "", required = false)]
40        url: String,
41
42        #[clap(
43            short = 'H',
44            long = "header",
45            value_parser = RequestData::parse_header,
46            value_name = "KEY:VALUE",
47            num_args = 1..,
48            required = false
49        )]
50        headers: Vec<(String, String)>,
51
52        #[clap(short = 'b', long, default_value = "", required = false)]
53        body: String,
54    },
55    #[clap(about = "Delete a collection or endpoint")]
56    Delete {
57        collection: String,
58
59        #[clap(short = 'e', long, default_value = "", required = false)]
60        endpoint: String,
61
62        #[clap(short, long, default_value = "false")]
63        yes: bool,
64    },
65    #[clap(about = "Copy a collection or endpoint")]
66    Copy {
67        collection: String,
68
69        #[clap(short = 'e', long, default_value = "", required = false)]
70        endpoint: String,
71
72        #[clap(short = 'c', long, default_value = "false", required = false)]
73        to_col: bool,
74
75        new_name: String,
76    },
77    #[clap(about = "Add a new collection")]
78    Col {
79        name: String,
80        url: String,
81
82        #[clap(
83            short = 'H',
84            long = "header",
85            value_parser = RequestData::parse_header,
86            value_name = "KEY:VALUE",
87            num_args = 1..,
88            required = false
89        )]
90        headers: Vec<(String, String)>,
91    },
92    #[clap(about = "Add a new endpoint to a collection")]
93    Endpoint {
94        collection: String,
95        name: String,
96        path: String,
97
98        #[clap(short = 'm', long, default_value = "GET")]
99        method: String,
100
101        #[clap(
102            short = 'H',
103            long = "header",
104            value_parser = RequestData::parse_header,
105            value_name = "KEY:VALUE",
106            num_args = 1..,
107            required = false
108        )]
109        headers: Vec<(String, String)>,
110
111        #[clap(short = 'b', long, default_value = "", required = false)]
112        body: String,
113    },
114}
115
116impl fmt::Display for ManagerCommands {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        match self {
119            ManagerCommands::List {
120                col,
121                endpoint,
122                quiet,
123                verbose,
124            } => write!(
125                f,
126                "List Command: col: '{}', endpoint: '{}', quiet: {}, verbose: {}",
127                col, endpoint, quiet, verbose
128            ),
129            ManagerCommands::Update {
130                collection,
131                endpoint,
132                url: _,
133                headers,
134                body,
135            } => {
136                write!(
137                    f,
138                    "Update Command: collection: '{}', endpoint: '{}', headers: {:?}, body: '{}'",
139                    collection, endpoint, headers, body
140                )
141            }
142            ManagerCommands::Delete {
143                collection,
144                endpoint,
145                yes,
146            } => {
147                write!(
148                    f,
149                    "Delete Command: collection: '{}', endpoint: '{}', yes: {}",
150                    collection, endpoint, yes
151                )
152            }
153            ManagerCommands::Copy {
154                collection,
155                endpoint,
156                to_col,
157                new_name,
158            } => {
159                write!(
160                    f,
161                    "Copy Command: collection: '{}', endpoint: '{}', To Col {}, new_name: '{}'",
162                    collection, endpoint, to_col, new_name
163                )
164            }
165            ManagerCommands::Col { name, url, headers } => {
166                write!(
167                    f,
168                    "Col Command: name: '{}', url: '{}', headers: {:?}",
169                    name, url, headers
170                )
171            }
172            ManagerCommands::Endpoint {
173                collection,
174                name,
175                path,
176                method,
177                headers,
178                body,
179            } => {
180                write!(f, "Endpoint Command: collection: '{}', name: '{}', path: '{}', method: '{}', headers: {:?}, body: '{}'",
181                    collection, name, path, method, headers, body)
182            }
183        }
184    }
185}
186
187impl ManagerCommands {
188    /// Get the default collection manager
189    pub fn get_manager() -> CollectionManager {
190        CollectionManager::default()
191    }
192
193    /// Get a RequestCommands for running an endpoint from a collection
194    pub fn get_endpoint_command(col_name: &str, ep_name: &str) -> Option<RequestCommands> {
195        let mut manager = Self::get_manager();
196        let col = manager.get_collection(col_name).ok()?;
197        // let req = manager.get_endpoint(collection, endpoint).ok()?;
198        let req = col
199            .get_request(ep_name)
200            .ok_or_else(|| CollectionError::EndpointNotFound(ep_name.to_string()))
201            .ok()?;
202        let data = RequestData {
203            url: format!("{}{}", col.url, req.endpoint),
204            headers: manager.get_endpoint_headers(col_name, ep_name),
205            body: req.body.clone().unwrap_or_default(),
206        };
207
208        Some(match req.method {
209            Method::Get => RequestCommands::Get { data },
210            Method::Post => RequestCommands::Post { data },
211            Method::Delete => RequestCommands::Delete { data },
212            Method::Patch => RequestCommands::Patch { data },
213            Method::Put => RequestCommands::Put { data },
214        })
215    }
216}