sure_client_rs/lib.rs
1//! # Sure API Client
2//!
3//! A type-safe Rust client for the Sure API, providing comprehensive access to
4//! financial data including transactions, categories, accounts, chat functionality, and authentication.
5//!
6//! ## Features
7//!
8//! - **Type-safe API**: Compile-time guarantees prevent common errors
9//! - **Comprehensive error handling**: Detailed, actionable error types
10//! - **Full async/await support**: Built on tokio and reqwest
11//! - **Complete API coverage**: Accounts, transactions, categories, chats, authentication, sync, and usage
12//! - **UUID-based identifiers**: Type-safe wrappers for all IDs
13//! - **Pagination support**: Built-in pagination handling for list endpoints
14//!
15//! ## Quick Start
16//!
17//! ### Using API Key Authentication
18//! ```no_run
19//! use sure_client_rs::{SureClient, Auth};
20//!
21//! #[tokio::main]
22//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
23//! // Create a client with your API key
24//! let client = SureClient::new(
25//! reqwest::Client::new(),
26//! Auth::api_key("your_api_key"),
27//! "http://localhost:3000".to_string().parse().unwrap(),
28//! );
29//!
30//! // List all categories
31//! let categories = client.get_categories().call().await?;
32//! for category in categories.items.categories {
33//! println!("{}: {}", category.name, category.color);
34//! }
35//!
36//! // List recent transactions
37//! let transactions = client.get_transactions()
38//! .page(1)
39//! .per_page(25)
40//! .call()
41//! .await?;
42//!
43//! for transaction in transactions.items.transactions {
44//! println!("{}: {} {}",
45//! transaction.name,
46//! transaction.amount,
47//! transaction.currency
48//! );
49//! }
50//!
51//! Ok(())
52//! }
53//! ```
54//!
55//! ### Using Bearer Token Authentication
56//! ```no_run
57//! use sure_client_rs::{SureClient, Auth};
58//!
59//! #[tokio::main]
60//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
61//! // Create a client with a JWT bearer token
62//! let client = SureClient::new(
63//! reqwest::Client::new(),
64//! Auth::bearer("your_jwt_token"),
65//! "http://localhost:3000".to_string().parse().unwrap(),
66//! );
67//!
68//! let categories = client.get_categories().call().await?;
69//! for category in categories.items.categories {
70//! println!("{}: {}", category.name, category.color);
71//! }
72//!
73//! Ok(())
74//! }
75//! ```
76//!
77//! ## Authentication
78//!
79//! The Sure API supports two authentication methods:
80//!
81//! ### API Key Authentication (X-Api-Key header)
82//! ```no_run
83//! use sure_client_rs::{SureClient, Auth};
84//!
85//! let client = SureClient::new(
86//! reqwest::Client::new(),
87//! Auth::api_key("your_api_key"),
88//! "http://localhost:3000".to_string().parse().unwrap(),
89//! );
90//! ```
91//!
92//! ### Bearer Token Authentication (Authorization header)
93//! ```no_run
94//! use sure_client_rs::{SureClient, Auth};
95//!
96//! let client = SureClient::new(
97//! reqwest::Client::new(),
98//! Auth::bearer("your_jwt_token"),
99//! "http://localhost:3000".to_string().parse().unwrap(),
100//! );
101//! ```
102//!
103//! ## Working with Categories
104//!
105//! ```no_run
106//! use sure_client_rs::{SureClient, BearerToken, CategoryId};
107//! use uuid::Uuid;
108//!
109//! # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
110//! // List the first page of categories
111//! let categories = client.get_categories()
112//! .page(1)
113//! .per_page(25)
114//! .call()
115//! .await?;
116//!
117//! // Get a specific category
118//! let category_id = CategoryId::new(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap());
119//! let category = client.get_category(&category_id).await?;
120//! # Ok(())
121//! # }
122//! ```
123//!
124//! ## Working with Transactions
125//!
126//! ```no_run
127//! use sure_client_rs::{SureClient, BearerToken, AccountId};
128//! use chrono::{DateTime, TimeZone, Utc};
129//! use rust_decimal::Decimal;
130//! use uuid::Uuid;
131//!
132//! # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
133//! // Create a transaction using the builder pattern
134//! let transaction = client.create_transaction()
135//! .account_id(AccountId::new(Uuid::new_v4()))
136//! .date(Utc.with_ymd_and_hms(2024, 1, 15, 12, 0, 0).unwrap())
137//! .amount(Decimal::new(4250, 2)) // $42.50
138//! .name("Grocery Store".to_string())
139//! .currency(iso_currency::Currency::USD)
140//! .call()
141//! .await?;
142//!
143//! // Update a transaction
144//! let updated = client.update_transaction()
145//! .id(&transaction.id)
146//! .notes("Updated notes".to_string())
147//! .call()
148//! .await?;
149//!
150//! // Delete a transaction
151//! let response = client.delete_transaction(&transaction.id).await?;
152//! # Ok(())
153//! # }
154//! ```
155//!
156//! ## Error Handling
157//!
158//! The client uses a comprehensive error type that covers both API-level and
159//! client-level errors:
160//!
161//! ```no_run
162//! use sure_client_rs::{SureClient, ApiError};
163//!
164//! # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
165//! match client.get_categories().call().await {
166//! Ok(categories) => {
167//! // Handle success
168//! }
169//! Err(ApiError::Unauthorized { message }) => {
170//! // Handle authentication error
171//! }
172//! Err(ApiError::NotFound { message }) => {
173//! // Handle not found error
174//! }
175//! Err(ApiError::RateLimited { message }) => {
176//! // Handle rate limiting
177//! }
178//! Err(e) => {
179//! // Handle other errors
180//! }
181//! }
182//! # Ok(())
183//! # }
184//! ```
185//!
186//! ## Development and Testing
187//!
188//! For local development, you can configure the client to use a different base URL:
189//!
190//! ```no_run
191//! use sure_client_rs::{SureClient, BearerToken};
192//!
193//! let client = SureClient::new(
194//! reqwest::Client::new(),
195//! BearerToken::new("your_api_key"),
196//! "http://localhost:3000".to_string().parse().unwrap(),
197//! );
198//! ```
199
200// Module declarations
201mod client;
202mod error;
203pub mod models;
204pub(crate) mod serde;
205mod types;
206
207// Public re-exports
208pub use client::SureClient;
209pub use error::{ApiError, ApiResult};
210pub use types::{
211 AccountId, ApiKey, Auth, BearerToken, CategoryId, MerchantId, TagId, TransactionId, ValuationId,
212};