jirust_cli/runners/jira_cmd_runners/issue_cmd_runner.rs
1use async_trait::async_trait;
2use jira_v3_openapi::apis::issue_search_api::search_for_issues_using_jql_post;
3use jira_v3_openapi::apis::issues_api::*;
4use jira_v3_openapi::models::user::AccountType;
5use jira_v3_openapi::models::{
6 CreatedIssue, IssueBean, IssueTransition, SearchRequestBean, Transitions, User,
7};
8use jira_v3_openapi::{apis::configuration::Configuration, models::IssueUpdateDetails};
9use serde_json::Value;
10use std::collections::HashMap;
11use std::io::Error;
12
13#[cfg(test)]
14use mockall::automock;
15
16use crate::args::commands::TransitionArgs;
17use crate::{
18 args::commands::IssueArgs,
19 config::config_file::{AuthData, ConfigFile},
20};
21
22/// Issue command runner
23/// This struct is responsible for running the issue command
24/// It uses the Jira API to perform the operations
25///
26/// # Fields
27///
28/// * `cfg` - Configuration object
29pub struct IssueCmdRunner {
30 /// Configuration object
31 cfg: Configuration,
32}
33
34/// Implementation of IssueCmdRunner
35///
36/// # Methods
37///
38/// * `new` - Creates a new instance of IssueCmdRunner
39/// * `assign_jira_issue` - Assigns a Jira issue to a user
40/// * `create_jira_issue` - Creates a Jira issue
41/// * `delete_jira_issue` - Deletes a Jira issue
42/// * `get_jira_issue` - Gets a Jira issue
43/// * `transition_jira_issue` - Transitions a Jira issue
44/// * `update_jira_issue` - Updates a Jira issue
45/// * `get_issue_available_transitions` - Gets available transitions for a Jira issue
46impl IssueCmdRunner {
47 /// Creates a new instance of IssueCmdRunner
48 ///
49 /// # Arguments
50 ///
51 /// * `cfg_file` - Configuration file
52 ///
53 /// # Returns
54 ///
55 /// * `IssueCmdRunner` - Instance of IssueCmdRunner
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// use jirust_cli::config::config_file::ConfigFile;
61 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueCmdRunner;
62 /// use toml::Table;
63 ///
64 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
65 ///
66 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
67 /// ```
68 pub fn new(cfg_file: &ConfigFile) -> IssueCmdRunner {
69 let mut config = Configuration::new();
70 let auth_data = AuthData::from_base64(cfg_file.get_auth_key());
71 config.base_path = cfg_file.get_jira_url().to_string();
72 config.basic_auth = Some((auth_data.0, Some(auth_data.1)));
73 IssueCmdRunner { cfg: config }
74 }
75
76 /// Assigns a Jira issue to a user
77 ///
78 /// # Arguments
79 ///
80 /// * `params` - Issue command parameters
81 ///
82 /// # Returns
83 ///
84 /// * `Value` - JSON value
85 ///
86 /// # Examples
87 ///
88 /// ```no_run
89 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
90 /// use jirust_cli::config::config_file::ConfigFile;
91 /// use toml::Table;
92 ///
93 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
94 /// # tokio_test::block_on(async {
95 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
96 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
97 /// let mut params = IssueCmdParams::new();
98 /// params.assignee = Some("assignee".to_string());
99 ///
100 /// let result = issue_cmd_runner.assign_jira_issue(params).await?;
101 /// # Ok(())
102 /// # })
103 /// # }
104 /// ```
105 pub async fn assign_jira_issue(
106 &self,
107 params: IssueCmdParams,
108 ) -> Result<Value, Box<dyn std::error::Error>> {
109 let user_data = User {
110 account_id: Some(params.assignee.expect("Assignee is required")),
111 account_type: Some(AccountType::Atlassian),
112 ..Default::default()
113 };
114
115 let i_key = if let Some(key) = ¶ms.issue_key {
116 key.as_str()
117 } else {
118 return Err(Box::new(Error::other(
119 "Error assigning issue: Empty issue key".to_string(),
120 )));
121 };
122
123 Ok(assign_issue(&self.cfg, i_key, user_data).await?)
124 }
125
126 /// Creates a Jira issue
127 ///
128 /// # Arguments
129 ///
130 /// * `params` - Issue command parameters
131 ///
132 /// # Returns
133 ///
134 /// * `CreatedIssue` - Created issue
135 ///
136 /// # Examples
137 ///
138 /// ```no_run
139 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
140 /// use jirust_cli::config::config_file::ConfigFile;
141 /// use toml::Table;
142 ///
143 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
144 /// # tokio_test::block_on(async {
145 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
146 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
147 /// let params = IssueCmdParams::new();
148 ///
149 /// let result = issue_cmd_runner.create_jira_issue(params).await?;
150 /// # Ok(())
151 /// # })
152 /// # }
153 /// ```
154 pub async fn create_jira_issue(
155 &self,
156 params: IssueCmdParams,
157 ) -> Result<CreatedIssue, Box<dyn std::error::Error>> {
158 let mut issue_fields = params.issue_fields.unwrap_or_default();
159 issue_fields.insert(
160 "project".to_string(),
161 serde_json::json!({"key": params.project_key.expect("Project Key is required to create an issue!")}),
162 );
163 let issue_data = IssueUpdateDetails {
164 fields: Some(issue_fields),
165 history_metadata: None,
166 properties: None,
167 transition: None,
168 update: None,
169 };
170 Ok(create_issue(&self.cfg, issue_data, None).await?)
171 }
172
173 /// Deletes a Jira issue
174 ///
175 /// # Arguments
176 ///
177 /// * `params` - Issue command parameters
178 ///
179 /// # Returns
180 ///
181 /// * `()` - Empty tuple
182 ///
183 /// # Examples
184 ///
185 /// ```no_run
186 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
187 /// use jirust_cli::config::config_file::ConfigFile;
188 /// use toml::Table;
189 ///
190 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
191 /// # tokio_test::block_on(async {
192 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
193 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
194 /// let mut params = IssueCmdParams::new();
195 /// params.issue_key = Some("issue_key".to_string());
196 ///
197 /// let result = issue_cmd_runner.delete_jira_issue(params).await?;
198 /// # Ok(())
199 /// # })
200 /// # }
201 /// ```
202 pub async fn delete_jira_issue(
203 &self,
204 params: IssueCmdParams,
205 ) -> Result<(), Box<dyn std::error::Error>> {
206 let i_key = if let Some(key) = ¶ms.issue_key {
207 key.as_str()
208 } else {
209 return Err(Box::new(Error::other(
210 "Error deleting issue: Empty issue key".to_string(),
211 )));
212 };
213
214 Ok(delete_issue(&self.cfg, i_key, Some("true")).await?)
215 }
216
217 /// Gets a Jira issue
218 ///
219 /// # Arguments
220 ///
221 /// * `params` - Issue command parameters
222 ///
223 /// # Returns
224 ///
225 /// * `IssueBean` - Jira issue
226 ///
227 /// # Examples
228 ///
229 /// ```no_run
230 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
231 /// use jirust_cli::config::config_file::ConfigFile;
232 /// use toml::Table;
233 ///
234 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
235 /// # tokio_test::block_on(async {
236 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
237 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
238 /// let mut params = IssueCmdParams::new();
239 /// params.issue_key = Some("issue_key".to_string());
240 ///
241 /// let result = issue_cmd_runner.get_jira_issue(params).await?;
242 /// # Ok(())
243 /// # })
244 /// # }
245 /// ```
246 pub async fn get_jira_issue(
247 &self,
248 params: IssueCmdParams,
249 ) -> Result<IssueBean, Box<dyn std::error::Error>> {
250 let i_key = if let Some(key) = ¶ms.issue_key {
251 key.as_str()
252 } else {
253 return Err(Box::new(Error::other(
254 "Error retrieving issue: Empty issue key".to_string(),
255 )));
256 };
257 Ok(get_issue(&self.cfg, i_key, None, None, None, None, None, None).await?)
258 }
259
260 /// This method searches for Jira issues using the provided JQL query parameters.
261 ///
262 /// # Arguments
263 ///
264 /// * `params` - Issue command parameters
265 ///
266 /// # Returns
267 ///
268 /// * `Vec<IssueBean>` - A vector of Jira issue beans
269 ///
270 /// # Examples
271 ///
272 /// ```no_run
273 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
274 /// use jirust_cli::config::config_file::ConfigFile;
275 /// use toml::Table;
276 ///
277 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
278 /// # tokio_test::block_on(async {
279 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
280 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
281 /// let mut params = IssueCmdParams::new();
282 /// params.query = Some("field=value".to_string());
283 ///
284 /// let result = issue_cmd_runner.search_jira_issues(params).await?;
285 /// # Ok(())
286 /// # })
287 /// # }
288 /// ```
289 pub async fn search_jira_issues(
290 &self,
291 params: IssueCmdParams,
292 ) -> Result<Vec<IssueBean>, Box<dyn std::error::Error>> {
293 let search_params: SearchRequestBean = SearchRequestBean {
294 jql: params.query,
295 ..Default::default()
296 };
297 match search_for_issues_using_jql_post(&self.cfg, search_params).await {
298 Ok(result) => {
299 if let Some(issues) = result.issues {
300 Ok(issues)
301 } else {
302 Ok(vec![])
303 }
304 }
305 Err(e) => Err(Box::new(e)),
306 }
307 }
308
309 /// Transitions a Jira issue
310 ///
311 /// # Arguments
312 ///
313 /// * `params` - Issue command parameters
314 ///
315 /// # Returns
316 ///
317 /// * `Value` - Jira issue transition
318 ///
319 /// # Examples
320 ///
321 /// ```no_run
322 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
323 /// use jirust_cli::config::config_file::ConfigFile;
324 /// use toml::Table;
325 ///
326 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
327 /// # tokio_test::block_on(async {
328 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
329 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
330 ///
331 /// let mut params = IssueCmdParams::new();
332 /// params.transition = Some("transition_id".to_string());
333 ///
334 /// let result = issue_cmd_runner.transition_jira_issue(params).await?;
335 /// # Ok(())
336 /// # })
337 /// # }
338 /// ```
339 pub async fn transition_jira_issue(
340 &self,
341 params: IssueCmdParams,
342 ) -> Result<Value, Box<dyn std::error::Error>> {
343 let i_key = if let Some(key) = ¶ms.issue_key {
344 key.as_str()
345 } else {
346 return Err(Box::new(Error::other(
347 "Error with issue transition: Empty issue key".to_string(),
348 )));
349 };
350
351 let trans = if let Some(transition) = ¶ms.transition {
352 transition.as_str()
353 } else {
354 return Err(Box::new(Error::other(
355 "Error with issue transition: Empty transition".to_string(),
356 )));
357 };
358
359 let transition = IssueTransition {
360 id: Some(trans.to_string()),
361 ..Default::default()
362 };
363 let issue_data = IssueUpdateDetails {
364 fields: params.issue_fields,
365 history_metadata: None,
366 properties: None,
367 transition: Some(transition),
368 update: None,
369 };
370 Ok(do_transition(&self.cfg, i_key, issue_data).await?)
371 }
372
373 /// Updates a Jira issue
374 ///
375 /// # Arguments
376 ///
377 /// * `params` - Issue command parameters
378 ///
379 /// # Returns
380 ///
381 /// * `Value` - Jira issue update
382 ///
383 /// # Examples
384 ///
385 /// ```no_run
386 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueCmdParams};
387 /// use jirust_cli::config::config_file::ConfigFile;
388 /// use toml::Table;
389 ///
390 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
391 /// # tokio_test::block_on(async {
392 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
393 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
394 /// let params = IssueCmdParams::new();
395 ///
396 /// let result = issue_cmd_runner.update_jira_issue(params).await?;
397 /// # Ok(())
398 /// # })
399 /// # }
400 /// ```
401 pub async fn update_jira_issue(
402 &self,
403 params: IssueCmdParams,
404 ) -> Result<Value, Box<dyn std::error::Error>> {
405 let i_key = if let Some(key) = ¶ms.issue_key {
406 key.as_str()
407 } else {
408 return Err(Box::new(Error::other(
409 "Error updating issue: Empty issue key".to_string(),
410 )));
411 };
412
413 let issue_data = IssueUpdateDetails {
414 fields: params.issue_fields,
415 history_metadata: None,
416 properties: None,
417 transition: None,
418 update: None,
419 };
420 Ok(edit_issue(
421 &self.cfg,
422 i_key,
423 issue_data,
424 None,
425 None,
426 None,
427 Some(true),
428 None,
429 )
430 .await?)
431 }
432
433 /// Gets available transitions for a Jira issue
434 ///
435 /// # Arguments
436 ///
437 /// * `params` - Issue command parameters
438 ///
439 /// # Returns
440 ///
441 /// * `Transitions` - Jira issue transitions
442 ///
443 /// # Examples
444 ///
445 /// ```no_run
446 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::{IssueCmdRunner, IssueTransitionCmdParams};
447 /// use jirust_cli::config::config_file::ConfigFile;
448 /// use toml::Table;
449 ///
450 /// # fn main() -> Result<(), Box<dyn std::error::Error>> {
451 /// # tokio_test::block_on(async {
452 /// let cfg_file = ConfigFile::new("dXNlcm5hbWU6YXBpX2tleQ==".to_string(), "jira_url".to_string(), "standard_resolution".to_string(), "standard_resolution_comment".to_string(), Table::new());
453 /// let issue_cmd_runner = IssueCmdRunner::new(&cfg_file);
454 /// let mut params = IssueTransitionCmdParams::new();
455 /// params.issue_key = "issue_key".to_string();
456 ///
457 /// let result = issue_cmd_runner.get_issue_available_transitions(params).await?;
458 /// # Ok(())
459 /// # })
460 /// # }
461 /// ```
462 pub async fn get_issue_available_transitions(
463 &self,
464 params: IssueTransitionCmdParams,
465 ) -> Result<Transitions, Box<dyn std::error::Error>> {
466 Ok(get_transitions(
467 &self.cfg,
468 ¶ms.issue_key,
469 None,
470 None,
471 None,
472 Some(false),
473 None,
474 )
475 .await?)
476 }
477}
478
479/// Issue command parameters
480///
481/// # Fields
482///
483/// * `project_key` - Jira project key
484/// * `issue_key` - Jira issue key
485/// * `issue_fields` - Jira issue fields
486/// * `transition` - Jira issue transition
487/// * `assignee` - Jira issue assignee
488/// * `query` - Jira issue query
489pub struct IssueCmdParams {
490 /// Jira project key
491 pub project_key: Option<String>,
492 /// Jira issue key
493 pub issue_key: Option<String>,
494 /// Jira issue fields
495 pub issue_fields: Option<HashMap<String, Value>>,
496 /// Jira issue transition
497 pub transition: Option<String>,
498 /// Jira issue assignee
499 pub assignee: Option<String>,
500 /// Jira issue query
501 pub query: Option<String>,
502}
503
504/// Implementation of IssueCmdParams struct
505///
506/// # Methods
507///
508/// * `new` - Creates a new IssueCmdParams instance
509impl IssueCmdParams {
510 /// Creates a new IssueCmdParams instance
511 ///
512 /// # Returns
513 ///
514 /// * `IssueCmdParams` - Issue command parameters
515 ///
516 /// # Examples
517 ///
518 /// ```
519 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueCmdParams;
520 ///
521 /// let params = IssueCmdParams::new();
522 /// ```
523 pub fn new() -> IssueCmdParams {
524 IssueCmdParams {
525 project_key: Some("".to_string()),
526 issue_key: None,
527 issue_fields: None,
528 transition: None,
529 assignee: None,
530 query: None,
531 }
532 }
533}
534
535/// Implementation of From trait for IssueCmdParams struct
536/// to convert IssueArgs struct to IssueCmdParams struct
537impl From<&IssueArgs> for IssueCmdParams {
538 /// Converts IssueArgs struct to IssueCmdParams struct
539 /// to create a new IssueCmdParams instance
540 ///
541 /// # Arguments
542 ///
543 /// * `value` - IssueArgs struct
544 ///
545 /// # Returns
546 ///
547 /// * `IssueCmdParams` - Issue command parameters
548 ///
549 /// # Examples
550 ///
551 /// ```
552 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueCmdParams;
553 /// use jirust_cli::args::commands::{IssueArgs, PaginationArgs, OutputArgs, IssueActionValues};
554 /// use std::collections::HashMap;
555 /// use serde_json::Value;
556 ///
557 /// let issue_args = IssueArgs {
558 /// issue_act: IssueActionValues::Get,
559 /// project_key: Some("project_key".to_string()),
560 /// issue_key: Some("issue_key".to_string()),
561 /// issue_fields: Some(vec![("key".to_string(), r#"{ "key": "value" }"#.to_string())]),
562 /// transition_to: Some("transition_to".to_string()),
563 /// assignee: Some("assignee".to_string()),
564 /// query: None,
565 /// pagination: PaginationArgs { page_size: Some(20), page_offset: None },
566 /// output: OutputArgs { output_format: None, output_type: None },
567 /// };
568 ///
569 /// let params = IssueCmdParams::from(&issue_args);
570 ///
571 /// assert_eq!(params.project_key, Some("project_key".to_string()));
572 /// assert_eq!(params.issue_key.unwrap(), "issue_key".to_string());
573 /// assert_eq!(params.transition.unwrap(), "transition_to".to_string());
574 /// assert_eq!(params.assignee.unwrap(), "assignee".to_string());
575 /// ```
576 fn from(value: &IssueArgs) -> Self {
577 IssueCmdParams {
578 project_key: value.project_key.clone(),
579 issue_key: value.issue_key.clone(),
580 issue_fields: Some(
581 value
582 .issue_fields
583 .clone()
584 .unwrap_or_default()
585 .iter()
586 .map(|elem| {
587 (
588 elem.0.clone(),
589 serde_json::from_str(elem.1.clone().as_str()).unwrap_or(Value::Null),
590 )
591 })
592 .collect::<HashMap<_, _>>(),
593 ),
594 transition: value.transition_to.clone(),
595 assignee: value.assignee.clone(),
596 query: value.query.clone(),
597 }
598 }
599}
600
601/// Issue transition command parameters
602///
603/// # Fields
604///
605/// * `issue_key` - Jira issue key
606pub struct IssueTransitionCmdParams {
607 /// Jira issue key
608 pub issue_key: String,
609}
610
611/// Implementation of IssueTransitionCmdParams struct
612///
613/// # Methods
614///
615/// * `new` - Creates a new IssueTransitionCmdParams instance
616impl IssueTransitionCmdParams {
617 /// Creates a new IssueTransitionCmdParams instance
618 ///
619 /// # Returns
620 ///
621 /// * `IssueTransitionCmdParams` - Issue transition command parameters
622 ///
623 /// # Examples
624 ///
625 /// ```
626 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueTransitionCmdParams;
627 ///
628 /// let params = IssueTransitionCmdParams::new();
629 /// ```
630 pub fn new() -> IssueTransitionCmdParams {
631 IssueTransitionCmdParams {
632 issue_key: "".to_string(),
633 }
634 }
635}
636
637/// Implementation of From trait for IssueTransitionCmdParams struct
638/// to convert TransitionArgs struct to IssueTransitionCmdParams struct
639impl From<&TransitionArgs> for IssueTransitionCmdParams {
640 /// Converts TransitionArgs struct to IssueTransitionCmdParams struct
641 /// to create a new IssueTransitionCmdParams instance
642 ///
643 /// # Arguments
644 ///
645 /// * `value` - TransitionArgs struct
646 ///
647 /// # Returns
648 ///
649 /// * `IssueTransitionCmdParams` - Issue transition command parameters
650 ///
651 /// # Examples
652 ///
653 /// ```
654 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueTransitionCmdParams;
655 /// use jirust_cli::args::commands::{TransitionArgs, TransitionActionValues, OutputArgs};
656 ///
657 /// let transition_args = TransitionArgs {
658 /// transition_act: TransitionActionValues::List,
659 /// issue_key: "issue_key".to_string(),
660 /// output: OutputArgs { output_format: None, output_type: None },
661 /// };
662 ///
663 /// let params = IssueTransitionCmdParams::from(&transition_args);
664 ///
665 /// assert_eq!(params.issue_key, "issue_key".to_string());
666 /// ```
667 fn from(value: &TransitionArgs) -> Self {
668 IssueTransitionCmdParams {
669 issue_key: value.issue_key.clone(),
670 }
671 }
672}
673
674/// Default implementation for IssueCmdParams struct
675impl Default for IssueTransitionCmdParams {
676 /// Creates a default IssueTransitionCmdParams instance
677 ///
678 /// # Returns
679 ///
680 /// A IssueTransitionCmdParams instance with default values
681 ///
682 /// # Examples
683 ///
684 /// ```
685 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueTransitionCmdParams;
686 ///
687 /// let params = IssueTransitionCmdParams::default();
688 ///
689 /// assert_eq!(params.issue_key, "".to_string());
690 /// ```
691 fn default() -> Self {
692 IssueTransitionCmdParams::new()
693 }
694}
695
696/// Default implementation for IssueCmdParams struct
697impl Default for IssueCmdParams {
698 /// Creates a default IssueCmdParams instance
699 ///
700 /// # Returns
701 ///
702 /// A IssueCmdParams instance with default values
703 ///
704 /// # Examples
705 ///
706 /// ```
707 /// use jirust_cli::runners::jira_cmd_runners::issue_cmd_runner::IssueCmdParams;
708 ///
709 /// let params = IssueCmdParams::default();
710 ///
711 /// assert_eq!(params.project_key, Some("".to_string()));
712 /// assert_eq!(params.issue_key, None);
713 /// assert_eq!(params.issue_fields, None);
714 /// assert_eq!(params.transition, None);
715 /// assert_eq!(params.assignee, None);
716 /// ```
717 fn default() -> Self {
718 IssueCmdParams::new()
719 }
720}
721
722#[cfg_attr(test, automock)]
723#[async_trait(?Send)]
724pub trait IssueCmdRunnerApi: Send + Sync {
725 async fn assign_jira_issue(
726 &self,
727 params: IssueCmdParams,
728 ) -> Result<Value, Box<dyn std::error::Error>>;
729
730 async fn create_jira_issue(
731 &self,
732 params: IssueCmdParams,
733 ) -> Result<CreatedIssue, Box<dyn std::error::Error>>;
734
735 async fn delete_jira_issue(
736 &self,
737 params: IssueCmdParams,
738 ) -> Result<(), Box<dyn std::error::Error>>;
739
740 async fn get_jira_issue(
741 &self,
742 params: IssueCmdParams,
743 ) -> Result<IssueBean, Box<dyn std::error::Error>>;
744
745 async fn search_jira_issues(
746 &self,
747 params: IssueCmdParams,
748 ) -> Result<Vec<IssueBean>, Box<dyn std::error::Error>>;
749
750 async fn transition_jira_issue(
751 &self,
752 params: IssueCmdParams,
753 ) -> Result<Value, Box<dyn std::error::Error>>;
754
755 async fn update_jira_issue(
756 &self,
757 params: IssueCmdParams,
758 ) -> Result<Value, Box<dyn std::error::Error>>;
759
760 async fn get_issue_available_transitions(
761 &self,
762 params: IssueTransitionCmdParams,
763 ) -> Result<Transitions, Box<dyn std::error::Error>>;
764}
765
766#[async_trait(?Send)]
767impl IssueCmdRunnerApi for IssueCmdRunner {
768 async fn assign_jira_issue(
769 &self,
770 params: IssueCmdParams,
771 ) -> Result<Value, Box<dyn std::error::Error>> {
772 IssueCmdRunner::assign_jira_issue(self, params).await
773 }
774
775 async fn create_jira_issue(
776 &self,
777 params: IssueCmdParams,
778 ) -> Result<CreatedIssue, Box<dyn std::error::Error>> {
779 IssueCmdRunner::create_jira_issue(self, params).await
780 }
781
782 async fn delete_jira_issue(
783 &self,
784 params: IssueCmdParams,
785 ) -> Result<(), Box<dyn std::error::Error>> {
786 IssueCmdRunner::delete_jira_issue(self, params).await
787 }
788
789 async fn get_jira_issue(
790 &self,
791 params: IssueCmdParams,
792 ) -> Result<IssueBean, Box<dyn std::error::Error>> {
793 IssueCmdRunner::get_jira_issue(self, params).await
794 }
795
796 async fn search_jira_issues(
797 &self,
798 params: IssueCmdParams,
799 ) -> Result<Vec<IssueBean>, Box<dyn std::error::Error>> {
800 IssueCmdRunner::search_jira_issues(self, params).await
801 }
802
803 async fn transition_jira_issue(
804 &self,
805 params: IssueCmdParams,
806 ) -> Result<Value, Box<dyn std::error::Error>> {
807 IssueCmdRunner::transition_jira_issue(self, params).await
808 }
809
810 async fn update_jira_issue(
811 &self,
812 params: IssueCmdParams,
813 ) -> Result<Value, Box<dyn std::error::Error>> {
814 IssueCmdRunner::update_jira_issue(self, params).await
815 }
816
817 async fn get_issue_available_transitions(
818 &self,
819 params: IssueTransitionCmdParams,
820 ) -> Result<Transitions, Box<dyn std::error::Error>> {
821 IssueCmdRunner::get_issue_available_transitions(self, params).await
822 }
823}