statbook/
lib.rs

1//! # Statbook
2//!
3//! A high-performance Rust library for accessing sports statistics and news data with concurrent API calls,
4//! comprehensive error handling, and flexible configuration options.
5//!
6//! Currently supports NFL player data via [MySportsFeeds.com](https://www.mysportsfeeds.com)
7//! and news data via [NewsAPI.org](https://newsapi.org) with plans to expand to other sports and data sources.
8//!
9//! ## Features
10//!
11//! - **Concurrent API calls** for improved performance
12//! - **Comprehensive error handling** with detailed error types
13//! - **Flexible configuration** with builder pattern and environment variables
14//! - **Built-in testing utilities** with mock providers
15//! - **Multiple fetch strategies** (stats-only, news-only, or both)
16//! - **Extensible architecture** with trait-based providers
17//!
18//! ## How-to
19//!
20//! ### Set up API credentials:
21//!
22//! ```bash
23//! export STATS_API_KEY="your-mysportsfeeds-api-key"
24//! export NEWS_API_KEY="your-newsapi-key"
25//! ```
26//! ### Flexible API Functions
27//!
28//! ```rust,no_run
29//! use statbook::{
30//!     StatbookClient, NewsQuery, Season,
31//!     api::players::{get_player_stats, get_player_news, get_player_summary}
32//! };
33//!
34//! # #[tokio::main]
35//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
36//! let client = StatbookClient::from_env()?;
37//!
38//! // Get only player statistics (faster)
39//! let stats = get_player_stats(&client, "josh-allen", None, &Season::Regular).await?;
40//!
41//! // Get only news articles
42//! let query = NewsQuery::for_player("josh-allen").with_page_size(10);
43//! let news = get_player_news(&client, &query).await?;
44//!
45//! // Get essential player info with news (always fetches both)
46//! let summary = get_player_summary(&client, "josh-allen", None, &Season::Regular).await?;
47//! # Ok(())
48//! # }
49//! ```
50//!
51//! ### Custom Configuration
52//!
53//! ```rust,no_run
54//! use statbook::{StatbookClient, StatbookConfig, NewsConfig, SortBy};
55//!
56//! # fn main() -> Result<(), Box<dyn std::error::Error>> {
57//! // Custom news configuration
58//! let news_config = NewsConfig::new()
59//!     .with_max_articles(15)
60//!     .with_days_back(30)
61//!     .with_sort_by(SortBy::Relevancy);
62//!
63//! // Build configuration
64//! let config = StatbookConfig::builder()
65//!     .stats_api_key("your-stats-key")
66//!     .news_api_key("your-news-key")
67//!     .news_config(news_config)
68//!     .build()?;
69//!
70//! let client = StatbookClient::new(config);
71//! # Ok(())
72//! # }
73//! ```
74//!
75//! ### Error Handling
76//!
77//! ```rust,no_run
78//! use statbook::{StatbookClient, StatbookError, Season, api::players::get_player_stats};
79//!
80//! # #[tokio::main]
81//! # async fn main() -> Result<(), Box<dyn std::error::Error>> {
82//! let client = StatbookClient::from_env()?;
83//!
84//! match get_player_stats(&client, "unknown-player", None, &Season::Regular).await {
85//!     Ok(stats) => println!("Found: {} {}", stats.first_name, stats.last_name),
86//!     Err(StatbookError::PlayerNotFound { name }) => {
87//!         println!("No player named '{}'", name);
88//!     }
89//!     Err(StatbookError::Network(e)) => {
90//!         println!("Network error: {}", e);
91//!     }
92//!     Err(e) => println!("Other error: {}", e),
93//! }
94//! # Ok(())
95//! # }
96//! ```
97//!
98//! ## Testing
99//!
100//! The library provides built-in testing utilities:
101//!
102//! ```rust
103//! use statbook::{create_mock_client, Season, api::players::get_player_stats};
104//!
105//! #[tokio::test]
106//! async fn test_my_app() {
107//!     let client = create_mock_client();  // No real API calls
108//!     let stats = get_player_stats(&client, "josh-allen", None, &Season::Regular).await.unwrap();
109//!     assert_eq!(stats.first_name, "Josh");
110//! }
111//! ```
112
113pub mod api;
114pub mod client;
115pub mod config;
116pub mod error;
117
118mod models;
119mod providers;
120mod test_utils;
121mod utils;
122
123// Re-export main types for convenience
124pub use client::StatbookClient;
125pub use config::{NewsConfig, SortBy, StatbookConfig};
126pub use error::{Result, StatbookError};
127pub use models::{Article, NewsQuery, PlayerNews, PlayerStats, PlayerSummary, Season};
128pub use providers::{MockNewsProvider, MockStatsProvider, NewsProvider, StatsProvider};
129
130// Re-export test utilities directly
131pub use test_utils::{
132    create_custom_mock_client, create_mock_client, init_integration_test_client,
133    skip_if_no_credentials,
134};