todoist_api/lib.rs
1//! # Todoist-api
2//!
3//! A Rust wrapper for the Todoist REST API v2.
4//!
5//! ## Features
6//!
7//! - Async/await support
8//! - Full CRUD operations for tasks
9//! - Project and label management
10//! - Comprehensive error handling with specific error types
11//! - Rate limiting detection and retry information
12//! - Serde serialization/deserialization
13//!
14//! ## Example
15//!
16//! ```rust,no_run
17//! use todoist_api::{TodoistWrapper, TodoistError, TodoistResult};
18//! use todoist_api::models::CreateTaskArgs;
19//!
20//! #[tokio::main]
21//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
22//! let todoist = TodoistWrapper::new("your-api-token".to_string());
23//!
24//! // Get all tasks with error handling
25//! match todoist.get_tasks().await {
26//! Ok(tasks) => println!("Found {} tasks", tasks.len()),
27//! Err(TodoistError::RateLimited { retry_after, message }) => {
28//! println!("Rate limited: {} (retry after {} seconds)", message, retry_after.unwrap_or(0));
29//! }
30//! Err(TodoistError::AuthenticationError { message }) => {
31//! println!("Authentication failed: {}", message);
32//! }
33//! Err(e) => println!("Other error: {}", e),
34//! }
35//!
36//! // Create a new task
37//! let args = CreateTaskArgs {
38//! content: "Buy groceries".to_string(),
39//! project_id: None,
40//! ..Default::default()
41//! };
42//! let new_task = todoist.create_task(&args).await?;
43//! println!("Created task: {}", new_task.content);
44//!
45//! Ok(())
46//! }
47//! ```
48
49pub mod models;
50pub mod wrapper;
51
52pub use models::*;
53pub use wrapper::TodoistWrapper;
54
55// Re-export commonly used types
56pub use models::{TodoistError, TodoistResult};
57
58#[cfg(test)]
59mod tests {
60 use super::*;
61
62 #[test]
63 fn test_todoist_wrapper_creation() {
64 let _wrapper = TodoistWrapper::new("test-token".to_string());
65 // Test that the wrapper was created successfully without panicking
66 // We can't access private fields, so we just verify creation works
67 // No assertion needed - if this function completes without panic, the test passes
68 }
69
70 #[test]
71 fn test_library_exports() {
72 // Test that all main types are properly exported
73 let _task: Task = Task {
74 id: "test".to_string(),
75 content: "test".to_string(),
76 description: "test".to_string(),
77 project_id: "test".to_string(),
78 section_id: None,
79 parent_id: None,
80 order: 1,
81 priority: 1,
82 is_completed: false,
83 labels: vec![],
84 created_at: "2024-01-01T00:00:00Z".to_string(),
85 due: None,
86 deadline: None,
87 duration: None,
88 assignee_id: None,
89 url: "https://todoist.com".to_string(),
90 comment_count: 0,
91 };
92
93 let _project: Project = Project {
94 id: "test".to_string(),
95 name: "test".to_string(),
96 comment_count: 0,
97 order: 1,
98 color: "blue".to_string(),
99 is_shared: false,
100 is_favorite: false,
101 is_inbox_project: false,
102 is_team_inbox: false,
103 view_style: "list".to_string(),
104 url: "https://todoist.com".to_string(),
105 parent_id: None,
106 };
107
108 let _label: Label = Label {
109 id: "test".to_string(),
110 name: "test".to_string(),
111 color: "red".to_string(),
112 order: 1,
113 is_favorite: false,
114 };
115
116 let _wrapper: TodoistWrapper = TodoistWrapper::new("test".to_string());
117
118 // Test that Result is properly exported
119 let _result: TodoistResult<()> = Ok(());
120 }
121
122 #[test]
123 fn test_argument_types() {
124 // Test that argument types can be created and used
125 let task_args = CreateTaskArgs {
126 content: "Test task".to_string(),
127 priority: Some(3),
128 ..Default::default()
129 };
130
131 assert_eq!(task_args.content, "Test task");
132 assert_eq!(task_args.priority, Some(3));
133
134 let project_args = CreateProjectArgs {
135 name: "Test project".to_string(),
136 color: Some("blue".to_string()),
137 ..Default::default()
138 };
139
140 assert_eq!(project_args.name, "Test project");
141 assert_eq!(project_args.color, Some("blue".to_string()));
142 }
143}