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.classification);
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.classification);
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 sure_client_rs::models::category::Classification;
108//! use uuid::Uuid;
109//!
110//! # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
111//! // Get expense categories
112//! let categories = client.get_categories()
113//! .page(1)
114//! .per_page(25)
115//! .classification(Classification::Expense)
116//! .call()
117//! .await?;
118//!
119//! // Get a specific category
120//! let category_id = CategoryId::new(Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap());
121//! let category = client.get_category(&category_id).await?;
122//! # Ok(())
123//! # }
124//! ```
125//!
126//! ## Working with Transactions
127//!
128//! ```no_run
129//! use sure_client_rs::{SureClient, BearerToken, AccountId};
130//! use chrono::{DateTime, TimeZone, Utc};
131//! use rust_decimal::Decimal;
132//! use uuid::Uuid;
133//!
134//! # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
135//! // Create a transaction using the builder pattern
136//! let transaction = client.create_transaction()
137//! .account_id(AccountId::new(Uuid::new_v4()))
138//! .date(Utc.with_ymd_and_hms(2024, 1, 15, 12, 0, 0).unwrap())
139//! .amount(Decimal::new(4250, 2)) // $42.50
140//! .name("Grocery Store".to_string())
141//! .currency(iso_currency::Currency::USD)
142//! .call()
143//! .await?;
144//!
145//! // Update a transaction
146//! let updated = client.update_transaction()
147//! .id(&transaction.id)
148//! .notes("Updated notes".to_string())
149//! .call()
150//! .await?;
151//!
152//! // Delete a transaction
153//! let response = client.delete_transaction(&transaction.id).await?;
154//! # Ok(())
155//! # }
156//! ```
157//!
158//! ## Error Handling
159//!
160//! The client uses a comprehensive error type that covers both API-level and
161//! client-level errors:
162//!
163//! ```no_run
164//! use sure_client_rs::{SureClient, ApiError};
165//!
166//! # async fn example(client: SureClient) -> Result<(), Box<dyn std::error::Error>> {
167//! match client.get_categories().call().await {
168//! Ok(categories) => {
169//! // Handle success
170//! }
171//! Err(ApiError::Unauthorized { message }) => {
172//! // Handle authentication error
173//! }
174//! Err(ApiError::NotFound { message }) => {
175//! // Handle not found error
176//! }
177//! Err(ApiError::RateLimited { message }) => {
178//! // Handle rate limiting
179//! }
180//! Err(e) => {
181//! // Handle other errors
182//! }
183//! }
184//! # Ok(())
185//! # }
186//! ```
187//!
188//! ## Development and Testing
189//!
190//! For local development, you can configure the client to use a different base URL:
191//!
192//! ```no_run
193//! use sure_client_rs::{SureClient, BearerToken};
194//!
195//! let client = SureClient::new(
196//! reqwest::Client::new(),
197//! BearerToken::new("your_api_key"),
198//! "http://localhost:3000".to_string().parse().unwrap(),
199//! );
200//! ```
201
202// Module declarations
203mod client;
204mod error;
205pub mod models;
206pub(crate) mod serde;
207mod types;
208
209// Public re-exports
210pub use client::SureClient;
211pub use error::{ApiError, ApiResult};
212pub use types::{
213 AccountId, ApiKey, Auth, BearerToken, CategoryId, MerchantId, TagId, TransactionId,
214};