coman/core/
endpoint_ops.rs

1use std::collections::HashMap;
2
3use crate::core::collection_manager::CollectionResult;
4use crate::core::errors::CollectionError;
5use crate::core::utils::merge_headers;
6use crate::{Collection, CollectionManager, Method, Request};
7
8impl CollectionManager {
9    /// Get the full URL for an endpoint (base URL + endpoint path)
10    pub fn get_endpoint_url(
11        mut self,
12        collection: &str,
13        endpoint: &str,
14    ) -> CollectionResult<String> {
15        let col = self.get_collection(collection)?;
16        let req = col
17            .get_request(endpoint)
18            .ok_or_else(|| CollectionError::EndpointNotFound(endpoint.to_string()))?;
19        Ok(format!("{}{}", col.url, req.endpoint))
20    }
21
22    /// Get merged headers for an endpoint (collection headers + endpoint headers)
23    pub fn get_endpoint_headers(
24        mut self,
25        collection: &str,
26        endpoint: &str,
27    ) -> Vec<(String, String)> {
28        let col = self.get_collection(collection).unwrap();
29        let req = col.get_request(endpoint).unwrap();
30
31        let mut merged: HashMap<String, String> = HashMap::new();
32        for (k, v) in &col.headers {
33            merged.insert(k.clone(), v.clone());
34        }
35        for (k, v) in &req.headers {
36            merged.insert(k.clone(), v.clone());
37        }
38
39        merged.into_iter().collect()
40    }
41
42    /// Add an endpoint to a collection
43    ///
44    /// If an endpoint with the same name exists, it will be updated.
45    pub fn add_endpoint(
46        mut self,
47        collection: &str,
48        name: &str,
49        path: &str,
50        method: Method,
51        headers: Vec<(String, String)>,
52        body: Option<String>,
53    ) -> CollectionResult<()> {
54        let collections = self
55            .loaded_collections
56            .as_mut()
57            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
58
59        let col = collections
60            .iter_mut()
61            .find(|c| c.name == collection)
62            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
63
64        let request = Request {
65            name: name.to_string(),
66            endpoint: path.to_string(),
67            method,
68            headers,
69            body,
70        };
71
72        let mut requests = col.requests.clone().unwrap_or_default();
73        requests.retain(|r| r.name != name);
74        requests.push(request);
75        col.requests = Some(requests);
76
77        self.save_collections()?;
78        Ok(())
79    }
80
81    /// Update an endpoint in a collection
82    pub fn update_endpoint(
83        mut self,
84        collection: &str,
85        endpoint: &str,
86        path: Option<&str>,
87        headers: Option<Vec<(String, String)>>,
88        body: Option<String>,
89    ) -> CollectionResult<()> {
90        let collections = self
91            .loaded_collections
92            .as_mut()
93            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
94
95        let col = collections
96            .iter_mut()
97            .find(|c| c.name == collection)
98            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
99
100        if let Some(requests) = col.requests.as_mut() {
101            let req = requests
102                .iter_mut()
103                .find(|r| r.name == endpoint)
104                .ok_or_else(|| CollectionError::EndpointNotFound(endpoint.to_string()))?;
105
106            if let Some(path) = path {
107                req.endpoint = path.to_string();
108            }
109
110            if let Some(new_headers) = headers {
111                req.headers = merge_headers(req.headers.clone(), &new_headers);
112            }
113
114            if let Some(new_body) = body {
115                req.body = if new_body.is_empty() {
116                    None
117                } else {
118                    Some(new_body)
119                };
120            }
121        } else {
122            return Err(CollectionError::EndpointNotFound(endpoint.to_string()));
123        }
124
125        self.save_collections()?;
126        Ok(())
127    }
128
129    /// Copy an endpoint within the same collection or to another collection
130    pub fn copy_endpoint(
131        mut self,
132        collection: &str,
133        endpoint: &str,
134        new_name: &str,
135        to_collection: Option<&str>,
136    ) -> CollectionResult<()> {
137        let collections = self
138            .loaded_collections
139            .as_mut()
140            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
141
142        // Find the source endpoint
143        let source_col = collections
144            .iter()
145            .find(|c| c.name == collection)
146            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
147
148        let source_req = source_col
149            .requests
150            .as_ref()
151            .and_then(|r| r.iter().find(|r| r.name == endpoint))
152            .ok_or_else(|| CollectionError::EndpointNotFound(endpoint.to_string()))?;
153
154        let mut new_req = source_req.clone();
155
156        if let Some(target_col_name) = to_collection {
157            // Copy to another collection (keep original name)
158            let target_col = collections
159                .iter_mut()
160                .find(|c| c.name == target_col_name)
161                .ok_or_else(|| CollectionError::CollectionNotFound(target_col_name.to_string()))?;
162
163            let mut requests = target_col.requests.clone().unwrap_or_default();
164            requests.push(new_req);
165            target_col.requests = Some(requests);
166        } else {
167            // Copy within the same collection with a new name
168            new_req.name = new_name.to_string();
169
170            let col = collections
171                .iter_mut()
172                .find(|c| c.name == collection)
173                .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
174
175            let mut requests = col.requests.clone().unwrap_or_default();
176            requests.push(new_req);
177            col.requests = Some(requests);
178        }
179
180        self.save_collections()?;
181        Ok(())
182    }
183
184    /// Delete an endpoint from a collection
185    pub fn delete_endpoint(mut self, collection: &str, endpoint: &str) -> CollectionResult<()> {
186        let collections = self
187            .loaded_collections
188            .as_mut()
189            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
190
191        let col = collections
192            .iter_mut()
193            .find(|c| c.name == collection)
194            .ok_or_else(|| CollectionError::CollectionNotFound(collection.to_string()))?;
195
196        if let Some(requests) = col.requests.as_mut() {
197            let original_len = requests.len();
198            requests.retain(|r| r.name != endpoint);
199
200            if requests.len() == original_len {
201                return Err(CollectionError::EndpointNotFound(endpoint.to_string()));
202            }
203        } else {
204            return Err(CollectionError::EndpointNotFound(endpoint.to_string()));
205        }
206
207        self.save_collections()?;
208        Ok(())
209    }
210
211    /// List all collections
212    pub fn list_collections(mut self) -> CollectionResult<Vec<Collection>> {
213        self.loaded_collections
214            .take()
215            .ok_or_else(|| CollectionError::Other("Collections not loaded!".to_string()))
216    }
217}