use serde::{Deserialize, Serialize};
use serde_json::Value;
pub const PROTOCOL_VERSION: &str = "1.0.0";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Request {
pub operation: Operation,
#[serde(default)]
pub args: Value,
pub actor: String,
pub request_id: String,
#[serde(default)]
pub client_version: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cwd: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub expected_db: Option<String>,
}
impl Request {
pub fn new(operation: Operation, actor: impl Into<String>) -> Self {
Self {
operation,
args: Value::Null,
actor: actor.into(),
request_id: uuid::Uuid::new_v4().to_string(),
client_version: PROTOCOL_VERSION.to_string(),
cwd: None,
expected_db: None,
}
}
pub fn with_args(mut self, args: impl Serialize) -> Self {
self.args = serde_json::to_value(args).unwrap_or(Value::Null);
self
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Response {
pub success: bool,
#[serde(skip_serializing_if = "Option::is_none")]
pub data: Option<Value>,
#[serde(skip_serializing_if = "Option::is_none")]
pub error: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub request_id: Option<String>,
}
impl Response {
pub fn success(data: impl Serialize) -> Self {
Self {
success: true,
data: Some(serde_json::to_value(data).unwrap_or(Value::Null)),
error: None,
request_id: None,
}
}
pub fn ok() -> Self {
Self {
success: true,
data: None,
error: None,
request_id: None,
}
}
pub fn error(message: impl Into<String>) -> Self {
Self {
success: false,
data: None,
error: Some(message.into()),
request_id: None,
}
}
pub fn with_request_id(mut self, id: impl Into<String>) -> Self {
self.request_id = Some(id.into());
self
}
pub fn parse_data<T: for<'de> Deserialize<'de>>(&self) -> Option<T> {
self.data.as_ref().and_then(|v| serde_json::from_value(v.clone()).ok())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum Operation {
Ping,
Health,
Status,
Create,
Show,
Update,
Delete,
List,
Count,
Ready,
Blocked,
Stale,
DepAdd,
DepRemove,
DepList,
LabelAdd,
LabelRemove,
LabelList,
CommentAdd,
CommentList,
Stats,
Compact,
CompactStats,
Export,
Import,
Config,
Shutdown,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthInfo {
pub pid: u32,
pub uptime_secs: u64,
pub version: String,
pub protocol_version: String,
pub compatible: bool,
pub database_path: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CreateArgs {
pub title: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub issue_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub parent_id: Option<String>,
#[serde(default)]
pub labels: Vec<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ShowArgs {
pub id: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct UpdateArgs {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<i32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DeleteArgs {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct ListArgs {
#[serde(skip_serializing_if = "Option::is_none")]
pub status: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub issue_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub label: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<usize>,
#[serde(default)]
pub include_closed: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DepArgs {
pub issue_id: String,
pub depends_on_id: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub dep_type: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LabelArgs {
pub issue_id: String,
pub label: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommentArgs {
pub issue_id: String,
pub text: String,
}