use bon::Builder;
use serde::Serialize;
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct StringComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<String>,
#[serde(rename = "in", skip_serializing_if = "Option::is_none")]
pub r#in: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nin: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contains: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub not_contains: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub contains_ignore_case: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub starts_with: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub ends_with: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub eq_ignore_case: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq_ignore_case: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct IdComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<String>,
#[serde(rename = "in", skip_serializing_if = "Option::is_none")]
pub r#in: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nin: Option<Vec<String>>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct NumberComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lt: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lte: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gt: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gte: Option<f64>,
#[serde(rename = "in", skip_serializing_if = "Option::is_none")]
pub r#in: Option<Vec<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nin: Option<Vec<f64>>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct NullableNumberComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lt: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lte: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gt: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gte: Option<f64>,
#[serde(rename = "in", skip_serializing_if = "Option::is_none")]
pub r#in: Option<Vec<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub nin: Option<Vec<f64>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub null: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct DateComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lt: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lte: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gt: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub gte: Option<String>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct BooleanComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct RelationExistsComparator {
#[serde(skip_serializing_if = "Option::is_none")]
pub eq: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub neq: Option<bool>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct IssueFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<IssueFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<IssueFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub title: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub description: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub number: Option<NumberComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<NullableNumberComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub estimate: Option<NullableNumberComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub due_date: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub completed_at: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<WorkflowStateFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub team: Option<TeamFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub assignee: Option<UserFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub creator: Option<UserFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub labels: Option<IssueLabelFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project: Option<ProjectFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub project_milestone: Option<ProjectMilestoneFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(into)]
pub parent: Option<Box<IssueFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_blocked_by_relations: Option<RelationExistsComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_blocking_relations: Option<RelationExistsComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_duplicate_relations: Option<RelationExistsComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub has_related_relations: Option<RelationExistsComparator>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct TeamFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<TeamFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<TeamFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub key: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<StringComparator>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct UserFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<UserFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<UserFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub display_name: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub active: Option<BooleanComparator>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct WorkflowStateFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<WorkflowStateFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<WorkflowStateFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<StringComparator>,
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
pub r#type: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub team: Option<TeamFilter>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct IssueLabelFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<IssueLabelFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<IssueLabelFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub team: Option<TeamFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
pub creator: Option<UserFilter>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct ProjectFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<ProjectFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<ProjectFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub state: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub health: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub priority: Option<NullableNumberComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub start_date: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_date: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub updated_at: Option<DateComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub lead: Option<UserFilter>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct ProjectMilestoneFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<ProjectMilestoneFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<ProjectMilestoneFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub name: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub target_date: Option<DateComparator>,
}
#[derive(Debug, Clone, Default, Serialize, Builder)]
#[serde(rename_all = "camelCase")]
#[non_exhaustive]
pub struct CommentFilter {
#[serde(skip_serializing_if = "Option::is_none")]
pub and: Option<Vec<CommentFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub or: Option<Vec<CommentFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub id: Option<IdComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub body: Option<StringComparator>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user: Option<UserFilter>,
#[serde(skip_serializing_if = "Option::is_none")]
#[builder(into)]
pub issue: Option<Box<IssueFilter>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<DateComparator>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn filters_skip_unset_fields_and_rename_in() {
let filter = IssueFilter::builder()
.title(
StringComparator::builder()
.contains("bug".to_string())
.build(),
)
.state(
WorkflowStateFilter::builder()
.r#type(
StringComparator::builder()
.r#in(vec!["started".to_string(), "unstarted".to_string()])
.build(),
)
.build(),
)
.parent(IssueFilter::default())
.build();
let value = serde_json::to_value(&filter).unwrap();
assert_eq!(
value,
serde_json::json!({
"title": { "contains": "bug" },
"state": { "type": { "in": ["started", "unstarted"] } },
"parent": {},
})
);
}
}