contextlite_client/lib.rs
1//! # ContextLite Rust Client
2//!
3//! A high-performance, async Rust client for the ContextLite context engine.
4//!
5//! ## Features
6//!
7//! - **Async/Await Support**: Built on Tokio for high-performance async operations
8//! - **Type Safety**: Comprehensive type definitions with builder patterns
9//! - **Error Handling**: Rich error types with proper error chaining
10//! - **Connection Pooling**: HTTP connection pooling for optimal performance
11//! - **Authentication**: Bearer token authentication support
12//! - **Validation**: Client-side validation for better error messages
13//! - **Flexible API**: Builder patterns for easy configuration
14//!
15//! ## Quick Start
16//!
17//! ```rust,no_run
18//! use contextlite_client::{ContextLiteClient, ClientConfig, Document, SearchQuery};
19//!
20//! #[tokio::main]
21//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
22//! // Create a client with default configuration
23//! let client = ContextLiteClient::new("http://localhost:8080")?;
24//!
25//! // Or with custom configuration
26//! let config = ClientConfig::new("http://localhost:8083")
27//! .with_auth_token("your-token")
28//! .with_timeout(60);
29//! let client = ContextLiteClient::with_config(config)?;
30//!
31//! // Add a document
32//! let document = Document::new("example.txt", "This is an example document");
33//! let doc_id = client.add_document(&document).await?;
34//!
35//! // Search for documents
36//! let query = SearchQuery::new("example").with_limit(10);
37//! let results = client.search(&query).await?;
38//!
39//! println!("Found {} documents", results.documents.len());
40//!
41//! Ok(())
42//! }
43//! ```
44//!
45//! ## Error Handling
46//!
47//! The client provides comprehensive error handling with detailed error messages:
48//!
49//! ```rust,no_run
50//! use contextlite_client::{ContextLiteClient, ContextLiteError};
51//!
52//! #[tokio::main]
53//! async fn main() {
54//! let client = ContextLiteClient::new("http://localhost:8080").unwrap();
55//!
56//! match client.health().await {
57//! Ok(health) => println!("Server is healthy: {}", health.status),
58//! Err(ContextLiteError::AuthError { message }) => {
59//! eprintln!("Authentication failed: {}", message);
60//! },
61//! Err(ContextLiteError::ServerError { status, message }) => {
62//! eprintln!("Server error {}: {}", status, message);
63//! },
64//! Err(err) => eprintln!("Error: {}", err),
65//! }
66//! }
67//! ```
68
69#![deny(missing_docs)]
70#![warn(clippy::all)]
71
72pub mod client;
73pub mod error;
74pub mod types;
75
76// Re-export main types for convenience
77pub use client::ContextLiteClient;
78pub use error::{ContextLiteError, Result};
79pub use types::{
80 CompleteHealthStatus, SmtInfo, DatabaseStats, Features,
81 ClientConfig, ContextRequest, ContextResponse, Document, DocumentReference,
82 SearchQuery, SearchResponse, StorageInfo,
83};
84
85/// Convenience alias for the main client type
86pub type Client = ContextLiteClient;
87
88#[cfg(test)]
89mod integration_tests {
90 use super::*;
91
92 #[tokio::test]
93 async fn test_client_creation_and_basic_operations() {
94 // This test requires a running ContextLite server
95 // Skip if server is not available
96 let client = match ContextLiteClient::new("http://127.0.0.1:8082") {
97 Ok(client) => client,
98 Err(_) => return, // Skip test if client creation fails
99 };
100
101 // Try to check health - this will fail if server is not running
102 if client.health().await.is_err() {
103 return; // Skip test if server is not available
104 }
105
106 // Test document operations
107 let mut metadata = std::collections::HashMap::new();
108 metadata.insert("test".to_string(), "true".to_string());
109 let document = Document::new("test.txt", "This is a test document")
110 .with_metadata(metadata);
111
112 let doc_id = client.add_document(&document).await.unwrap();
113 assert!(!doc_id.is_empty());
114
115 // Test search
116 let query = SearchQuery::new("test").with_limit(5);
117 let results = client.search(&query).await.unwrap();
118 assert!(!results.documents.is_empty());
119
120 // Test context assembly
121 let context_request = ContextRequest::new("test document")
122 .with_budget(1000)
123 .with_max_results(3);
124 let context = client.assemble_context(&context_request).await.unwrap();
125 assert!(context.total_documents > 0);
126
127 // Clean up
128 let _ = client.delete_document(&doc_id).await;
129 }
130}