todoist_api/
lib.rs

1//! # Todoist-api
2//!
3//! A Rust wrapper for the Todoist Unified API v1.
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(None, None).await {
26//!         Ok(response) => println!("Found {} tasks", response.results.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            user_id: "user123".to_string(),
76            content: "test".to_string(),
77            description: "test".to_string(),
78            project_id: "test".to_string(),
79            section_id: None,
80            parent_id: None,
81            added_by_uid: None,
82            assigned_by_uid: None,
83            responsible_uid: None,
84            labels: vec![],
85            deadline: None,
86            duration: None,
87            checked: false,
88            is_deleted: false,
89            added_at: "2024-01-01T00:00:00Z".to_string(),
90            completed_at: None,
91            completed_by_uid: None,
92            updated_at: None,
93            due: None,
94            priority: 1,
95            child_order: 0,
96            note_count: 0,
97            day_order: 0,
98            is_collapsed: false,
99        };
100
101        let _project: Project = Project {
102            id: "test".to_string(),
103            name: "test".to_string(),
104            color: "blue".to_string(),
105            is_shared: false,
106            is_favorite: false,
107            inbox_project: false,
108            view_style: "list".to_string(),
109            parent_id: None,
110            child_order: 0,
111            creator_uid: None,
112            created_at: None,
113            updated_at: None,
114            is_archived: false,
115            is_deleted: false,
116            is_frozen: false,
117            is_collapsed: false,
118            can_assign_tasks: false,
119            default_order: 0,
120            description: String::new(),
121            public_key: String::new(),
122            role: None,
123        };
124
125        let _label: Label = Label {
126            id: "test".to_string(),
127            name: "test".to_string(),
128            color: "red".to_string(),
129            order: Some(1),
130            is_favorite: false,
131        };
132
133        let _wrapper: TodoistWrapper = TodoistWrapper::new("test".to_string());
134
135        // Test that Result is properly exported
136        let _result: TodoistResult<()> = Ok(());
137    }
138
139    #[test]
140    fn test_argument_types() {
141        // Test that argument types can be created and used
142        let task_args = CreateTaskArgs {
143            content: "Test task".to_string(),
144            priority: Some(3),
145            ..Default::default()
146        };
147
148        assert_eq!(task_args.content, "Test task");
149        assert_eq!(task_args.priority, Some(3));
150
151        let project_args = CreateProjectArgs {
152            name: "Test project".to_string(),
153            color: Some("blue".to_string()),
154            ..Default::default()
155        };
156
157        assert_eq!(project_args.name, "Test project");
158        assert_eq!(project_args.color, Some("blue".to_string()));
159    }
160}