use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CrateInfo {
pub name: String,
pub description: Option<String>,
pub newest_version: String,
pub downloads: u64,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub homepage: Option<String>,
pub repository: Option<String>,
pub documentation: Option<String>,
pub keywords: Vec<String>,
pub categories: Vec<String>,
pub max_upload_size: Option<u64>,
pub license: Option<String>,
pub yanked: Option<bool>,
pub links: Option<CrateLinks>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CrateLinks {
pub owner_team: Option<String>,
pub owner_user: Option<String>,
pub reverse_dependencies: Option<String>,
pub version_downloads: Option<String>,
pub versions: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Version {
pub num: String,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub downloads: u64,
pub yanked: bool,
pub id: Option<u64>,
pub crate_size: Option<u64>,
pub published_by: Option<User>,
pub audit_actions: Option<Vec<AuditAction>>,
pub license: Option<String>,
pub links: Option<VersionLinks>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct User {
pub id: u64,
pub login: String,
pub name: Option<String>,
pub avatar: Option<String>,
pub url: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct AuditAction {
pub action: String,
pub user: User,
pub time: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VersionLinks {
pub dependencies: Option<String>,
pub version_downloads: Option<String>,
pub authors: Option<String>,
}
#[derive(Debug, Clone, PartialEq)]
pub enum CrateStatus {
Exists,
NotFound,
Yanked,
PartiallyYanked,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct CrateSearchResult {
pub name: String,
pub description: Option<String>,
pub newest_version: String,
pub downloads: u64,
pub exact_match: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Dependency {
#[serde(rename = "crate_id")]
pub name: String,
pub req: String,
#[serde(default)]
pub features: Vec<String>,
pub optional: bool,
pub default_features: bool,
pub target: Option<String>,
pub kind: String,
#[serde(default)]
pub downloads: Option<u64>,
}
impl Dependency {
pub fn name(&self) -> &str {
&self.name
}
pub fn version_req(&self) -> &str {
&self.req
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct DownloadStats {
pub total: u64,
pub versions: Vec<VersionDownload>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct VersionDownload {
pub version: String,
pub downloads: u64,
pub date: DateTime<Utc>,
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct Owner {
pub id: u64,
pub login: String,
pub name: Option<String>,
pub email: Option<String>,
pub avatar: Option<String>,
pub url: Option<String>,
pub kind: String, }
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum BatchInput {
CrateVersionMap(HashMap<String, String>),
CrateList { crates: Vec<String> },
Operations { operations: Vec<BatchOperation> },
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BatchOperation {
#[serde(flatten)]
pub target: BatchTarget,
pub operation: String,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(untagged)]
pub enum BatchTarget {
Single {
#[serde(rename = "crate")]
crate_name: String,
version: Option<String>,
},
Multiple { crates: Vec<String> },
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct CrateCheckResult {
pub crate_name: String,
pub exists: bool,
pub latest_version: Option<String>,
pub requested_version: Option<String>,
pub version_exists: Option<bool>,
pub error: Option<String>,
pub info: Option<CrateInfo>,
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct BatchResult {
pub results: Vec<CrateCheckResult>,
pub total_processed: usize,
pub successful: usize,
pub failed: usize,
pub processing_time_ms: u64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchRequest {
#[serde(flatten)]
pub input: BatchInput,
#[serde(default)]
pub options: BatchOptions,
}
#[derive(Debug, Serialize, Deserialize, Default)]
pub struct BatchOptions {
#[serde(default)]
pub include_details: bool,
#[serde(default)]
pub parallel: bool,
#[serde(default = "default_timeout")]
pub timeout_seconds: u64,
#[serde(default = "default_concurrency")]
pub max_concurrent: usize,
}
fn default_timeout() -> u64 {
30
}
fn default_concurrency() -> usize {
10
}
#[derive(Debug, Serialize, Deserialize)]
pub struct BatchResponse {
pub request_id: String,
pub status: String,
#[serde(flatten)]
pub result: BatchResult,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct HealthResponse {
pub status: String,
pub timestamp: DateTime<Utc>,
pub version: String,
pub uptime_seconds: u64,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct SearchParams {
pub q: String,
pub limit: Option<usize>,
pub offset: Option<usize>,
pub sort: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct MetricsResponse {
pub requests_total: u64,
pub requests_successful: u64,
pub requests_failed: u64,
pub average_response_time_ms: f64,
pub cache_hits: u64,
pub cache_misses: u64,
pub uptime_seconds: u64,
}
#[derive(Debug, Deserialize)]
pub struct CrateResponse {
#[serde(rename = "crate")]
pub crate_info: CrateApiInfo,
pub versions: Option<Vec<Version>>,
pub keywords: Option<Vec<Keyword>>,
pub categories: Option<Vec<Category>>,
}
#[derive(Debug, Deserialize)]
pub struct CrateApiInfo {
pub name: String,
pub description: Option<String>,
pub newest_version: String,
pub downloads: u64,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
pub homepage: Option<String>,
pub repository: Option<String>,
pub documentation: Option<String>,
pub max_upload_size: Option<u64>,
#[serde(rename = "recent_downloads")]
pub recent_downloads: Option<u64>,
}
#[derive(Debug, Deserialize)]
pub struct Keyword {
pub keyword: String,
}
#[derive(Debug, Deserialize)]
pub struct Category {
pub category: String,
}
#[derive(Debug, Deserialize)]
pub struct VersionsResponse {
pub versions: Vec<Version>,
}
#[derive(Debug, Deserialize)]
pub struct SearchResponse {
pub crates: Vec<CrateSearchResult>,
pub meta: SearchMeta,
}
#[derive(Debug, Deserialize)]
pub struct SearchMeta {
pub total: u32,
}
#[derive(Debug, Deserialize)]
pub struct DependenciesResponse {
pub dependencies: Vec<Dependency>,
}
#[derive(Debug, Deserialize)]
pub struct DownloadsResponse {
pub version_downloads: Vec<VersionDownloadApi>,
pub meta: DownloadsMeta,
}
#[derive(Debug, Deserialize)]
pub struct DownloadsMeta {
pub extra_downloads: Vec<ExtraDownload>,
}
#[derive(Debug, Deserialize)]
pub struct VersionDownloadApi {
pub version: String,
pub downloads: u64,
pub date: String, }
#[derive(Debug, Deserialize)]
pub struct ExtraDownload {
pub date: String, pub downloads: u64,
}
impl From<CrateApiInfo> for CrateInfo {
fn from(api_info: CrateApiInfo) -> Self {
Self {
name: api_info.name,
description: api_info.description,
newest_version: api_info.newest_version,
downloads: api_info.downloads,
created_at: api_info.created_at,
updated_at: api_info.updated_at,
homepage: api_info.homepage,
repository: api_info.repository,
documentation: api_info.documentation,
keywords: Vec::new(), categories: Vec::new(), max_upload_size: api_info.max_upload_size,
license: None,
yanked: None,
links: None,
}
}
}