use axum::{
extract::{Path, Query, State},
http::StatusCode,
Json,
};
use serde_json::json;
use uuid::Uuid;
use crate::{
error::{ApiError, ApiResult},
models::{PackageResult, PaginatedResponse, PurchaseRequest, PurchaseResponse, SearchRequest},
state::AppState,
};
pub async fn search_packages(
State(state): State<AppState>,
Query(req): Query<SearchRequest>,
) -> ApiResult<Json<PaginatedResponse<PackageResult>>> {
if req.query.is_empty() {
return Err(ApiError::BadRequest("Query cannot be empty".to_string()));
}
let limit = req.limit.unwrap_or(20);
let offset = req.offset.unwrap_or(0);
let results = vec![
PackageResult {
id: Uuid::new_v4().to_string(),
name: "api-client".to_string(),
version: "1.0.0".to_string(),
author: "example".to_string(),
description: "REST API client generator".to_string(),
downloads: 1250,
price: Some(19.99),
license: "MIT".to_string(),
rating: 4.8,
},
];
Ok(Json(PaginatedResponse {
data: results,
total: 1,
limit,
offset,
}))
}
pub async fn get_package(
State(_state): State<AppState>,
Path(package_id): Path<String>,
) -> ApiResult<Json<PackageResult>> {
if package_id.is_empty() {
return Err(ApiError::NotFound("Package not found".to_string()));
}
Ok(Json(PackageResult {
id: package_id,
name: "api-client".to_string(),
version: "1.0.0".to_string(),
author: "example".to_string(),
description: "REST API client generator".to_string(),
downloads: 1250,
price: Some(19.99),
license: "MIT".to_string(),
rating: 4.8,
}))
}
pub async fn purchase_package(
State(_state): State<AppState>,
Json(req): Json<PurchaseRequest>,
) -> ApiResult<(StatusCode, Json<PurchaseResponse>)> {
if req.package_id.is_empty() {
return Err(ApiError::BadRequest("Package ID required".to_string()));
}
let transaction_id = Uuid::new_v4().to_string();
Ok((
StatusCode::CREATED,
Json(PurchaseResponse {
transaction_id: transaction_id.clone(),
package_id: req.package_id,
price: 19.99,
status: "pending".to_string(),
payment_url: Some(format!(
"{}/checkout/{}",
"https://stripe.com", transaction_id
)),
}),
))
}
pub async fn download_package(
State(_state): State<AppState>,
Path((package_id, version)): Path<(String, String)>,
) -> ApiResult<Json<serde_json::Value>> {
if package_id.is_empty() {
return Err(ApiError::NotFound("Package not found".to_string()));
}
Ok(Json(json!({
"download_url": format!("https://s3.example.com/{}/{}", package_id, version),
"expires_in_secs": 3600,
})))
}
pub async fn list_purchases(
State(_state): State<AppState>,
Query(pagination): Query<serde_json::Value>,
) -> ApiResult<Json<PaginatedResponse<PackageResult>>> {
Ok(Json(PaginatedResponse {
data: vec![],
total: 0,
limit: 20,
offset: 0,
}))
}