issuecraft_core/
lib.rs

1use async_trait::async_trait;
2use facet::Facet;
3use facet_json::{DeserializeError, JsonError};
4use issuecraft_ql::{CloseReason, ExecutionEngine, ExecutionResult, ProjectId, UserId};
5
6#[derive(thiserror::Error, Debug)]
7pub enum ClientError {
8    #[error("Not implemented")]
9    NotImplemented,
10    #[error("This action is not supported by the chosen backend")]
11    NotSupported,
12    #[error("IQL error: {0}")]
13    IqlError(#[from] issuecraft_ql::IqlError),
14    #[error("Deserialization error: {0}")]
15    DeserializationError(#[from] DeserializeError<JsonError>),
16    #[error("Client specific: {0}")]
17    ClientSpecific(String),
18}
19
20#[derive(Debug, Clone, Facet)]
21pub struct UserInfo {
22    pub name: String,
23    pub display: Option<String>,
24    pub email: String,
25}
26
27#[derive(Debug, Clone, Facet)]
28pub struct ProjectInfo {
29    pub description: Option<String>,
30    pub owner: UserId,
31    pub display: Option<String>,
32}
33
34#[derive(Debug, Clone, Facet)]
35#[repr(C)]
36pub enum IssueStatus {
37    Open,
38    Assigned,
39    Blocked,
40    Closed { reason: CloseReason },
41}
42
43#[derive(Debug, Clone, Facet)]
44#[repr(C)]
45pub enum Priority {
46    Low,
47    Medium,
48    High,
49    Critical,
50}
51
52#[derive(Debug, Clone, Facet)]
53pub struct IssueInfo {
54    pub title: String,
55    pub description: Option<String>,
56    pub status: IssueStatus,
57    pub project: ProjectId,
58    pub priority: Option<Priority>,
59    pub assignee: Option<UserId>,
60}
61
62impl IssueInfo {
63    pub fn is_closed(&self) -> bool {
64        matches!(self.status, IssueStatus::Closed { .. })
65    }
66}
67
68#[derive(Debug, Clone, Facet)]
69pub struct CommentInfo {
70    pub created_at: time::UtcDateTime,
71    pub content: String,
72    pub author: UserId,
73}
74
75#[derive(Debug, Clone)]
76pub enum AuthenticationInfo {
77    Password { password: String },
78    Token { token: String },
79    Certificate { path: Vec<u8> },
80}
81
82#[derive(Debug, Clone)]
83pub struct LoginInfo {
84    pub user: String,
85    pub auth: AuthenticationInfo,
86}
87
88#[async_trait]
89pub trait Client {
90    async fn login(&mut self, _login: LoginInfo) -> Result<(), ClientError> {
91        Err(ClientError::NotSupported)
92    }
93    async fn logout(&mut self) -> Result<(), ClientError> {
94        Err(ClientError::NotSupported)
95    }
96    async fn query(&mut self, query: &str) -> Result<ExecutionResult, ClientError>;
97}
98
99#[async_trait]
100impl<E: ExecutionEngine + Send> Client for E {
101    async fn query(&mut self, query: &str) -> Result<ExecutionResult, ClientError> {
102        let result = self.execute(query).await?;
103        Ok(result)
104    }
105}
106
107pub trait Backend {
108    fn init(&mut self) {}
109}