This document outlines the dependencies between modules in the Serper SDK, showing how they interact and the data flow between them.
┌─────────┐ ┌─────────┐ ┌─────────┐
│ core │ │ utils │ │ config │
│ │ │ │ │ │
└─────┬───┘ └─────────┘ └───┬─────┘
│ │
│ ┌─────────┐ │
└────────┤ http │─────────┘
│ │
└────┬────┘
│
┌────▼────┐
│ search │
│ │
└─────────┘
core- Foundational types and error handlingutils- Common utilities and helpersconfig- Configuration management
http- HTTP transport and client functionality
search- High-level search operations
Internal Dependencies: None (foundational module)
External Dependencies:
thiserror- Error derive macrosserde- Serialization traits
Exports to other modules:
SerperError- Used by all modules for error handlingResult<T>- Used by all modules for return typesApiKey- Used by http and config modulesBaseUrl- Used by http and config modulesLocation,Pagination- Used by search module
Usage by other modules:
http- Uses ApiKey, BaseUrl, and error typessearch- Uses all core types and error handlingconfig- Uses error types for validationutils- Uses error types for validation functions
Internal Dependencies:
core::error- For SerperError and Result types
External Dependencies:
url- URL parsing and validationtokio::time- Async sleep functionalitystd::collections::HashMap- Collection utilities
Exports to other modules:
- URL validation functions - Used by config and http modules
- String validation functions - Used by all modules
- Collection utilities - Used by config and http modules
- Retry logic - Used by http and search modules
Usage by other modules:
core- Could use string validation (currently doesn't)http- Uses retry logic and URL validationsearch- Uses validation functions and retry logicconfig- Uses URL and string validation extensively
Internal Dependencies:
core::error- For error types and Result
External Dependencies:
std::time::Duration- Timeout configurationstd::collections::HashMap- Header storagestd::env- Environment variable access
Exports to other modules:
SdkConfig- Used by search and http modulesSdkConfigBuilder- Used by applications
Usage by other modules:
http- Uses timeout and header configurationsearch- Could use SdkConfig for service configuration- Applications use this for centralized configuration
Internal Dependencies:
core- All types (ApiKey, BaseUrl, errors, Result)search::query- SearchQuery typesearch::response- SearchResponse type and parsing
External Dependencies:
reqwest- HTTP client implementationserde- Serialization for request bodiestokio- Async runtime and synchronization
Exports to other modules:
HttpTransport- Low-level HTTP operationsSerperHttpClient- High-level HTTP client- Transport builders and configuration
Usage by other modules:
search- Uses SerperHttpClient for API operations- Could be used directly by applications for custom HTTP operations
Internal Dependencies:
core- All types and error handlinghttp- SerperHttpClient and transport configuration- Could use
utils- For validation and retry logic - Could use
config- For service configuration
External Dependencies:
serde- Serialization/deserializationtokio- Async operationsurl- URL parsing in response processingstd::collections::HashMap- Response metadata
Exports to other modules:
SearchService- Main service interfaceSearchQuery,SearchQueryBuilder- Query constructionSearchResponseand related types - Response handling- All response parsing utilities
Usage by other modules:
- This is the top-level module used by applications
- No other internal modules depend on search
- Application creates
SearchQueryusingsearchmodule - Search module validates query using
coretypes - Search module uses
httpmodule to make API request - HTTP module uses
core::ApiKeyandcore::BaseUrlfor authentication - HTTP module serializes request using
SearchQuery - HTTP module makes HTTP request using
reqwest - HTTP module parses response into
SearchResponse - Search module returns
SearchResponseto application
- Application creates
SdkConfigusingconfigmodule - Config module validates configuration using
utilsvalidation - Config module uses
coreerror types for validation errors - Application uses config to create
SearchService - Search service uses config to configure
httpclient
- Core module defines
SerperErrorenum - All modules use
core::Result<T>for error handling - Utils module creates validation errors using
core::SerperError - HTTP module converts
reqwest::ErrortoSerperError::Request - Search module propagates all errors to application
corehas no internal dependenciesutilsonly depends oncorefor error typesconfigonly depends oncorefor error types
httpdepends oncoreandsearchtypes (circular dependency handled via careful API design)searchdepends oncoreandhttp
search::queryandsearch::responsecould be more independenthttp::clienttightly coupled to search types
// Error handling
pub enum SerperError { /* ... */ }
pub type Result<T> = std::result::Result<T, SerperError>;
// Type safety
pub struct ApiKey(String);
pub struct BaseUrl(String);
pub struct Location { /* ... */ }
pub struct Pagination { /* ... */ }// Transport abstraction
pub struct HttpTransport;
impl HttpTransport {
pub async fn post_json<T>(&self, url: &str, api_key: &ApiKey, body: &T) -> Result<Response>;
}
// High-level client
pub struct SerperHttpClient;
impl SerperHttpClient {
pub async fn search(&self, query: &SearchQuery) -> Result<SearchResponse>;
}// Service interface
pub struct SearchService;
impl SearchService {
pub async fn search(&self, query: &SearchQuery) -> Result<SearchResponse>;
pub async fn search_multiple(&self, queries: &[SearchQuery]) -> Result<Vec<SearchResponse>>;
}
// Query construction
pub struct SearchQuery { /* ... */ }
pub struct SearchQueryBuilder { /* ... */ }
// Response handling
pub struct SearchResponse { /* ... */ }The SDK uses dependency inversion in several places:
SearchServicedepends onSerperHttpClientabstractionSerperHttpClientdepends onHttpTransportabstraction- This allows for easy mocking and testing
- Services accept configuration objects rather than individual parameters
- This allows for flexible configuration without changing service interfaces
- All modules use
core::SerperErrorrather than exposing underlying errors - This provides a consistent error handling interface
- Each module can be tested independently
coremodule has no dependencies (easy to test)utilsmodule only needscorefor error typesconfigmodule only needscoreand standard library
httpmodule needs mocking for network operationssearchmodule needshttpmocking- Full integration tests exercise all modules together
- Common test utilities could be extracted to a
test_utilsmodule - Mock implementations could be provided for key interfaces
- Extract Response Types: Move response types to a separate module
- Plugin Architecture: Allow custom transport implementations
- Async Traits: Use async traits for better abstraction
- Dependency Injection: Make dependencies more explicit
- Mock Traits: Provide mock implementations for testing
- Test Builders: Create test data builders for complex types
- Lazy Loading: Load heavy dependencies only when needed
- Connection Pooling: Better connection reuse across modules
- Caching: Add caching layer between modules
core::SerperError- Error types are foundationalcore::Result<T>- Result type alias is standardSearchService::search()- Main API method is stable
- HTTP transport configuration - May add new options
- Query builder methods - May add new parameters
- Response parsing - May add new response types
- Retry configuration - May be redesigned
- Concurrent search limits - May become more sophisticated
- Custom transport plugins - Not yet implemented
SearchServicepublic API will remain stableSearchQueryandSearchResponsewill maintain backwards compatibility- Core error types will not change
- New functionality added via new methods rather than changing existing ones
- Optional parameters added via builder patterns
- New response fields added as optional
- Deprecated methods will be marked clearly
- Migration guides provided for breaking changes
- Old APIs supported for at least 2 major versions