use std::collections::BTreeMap;
use std::sync::Arc;
use axum::Router;
use axum::routing::{delete, get, put};
use ferro_blob_store::BlobStore;
use ferro_blob_store::Digest;
use tokio::sync::RwLock;
use crate::config::IndexConfig;
use crate::handlers::{
handle_config_json, handle_download, handle_git_index_stub, handle_owners_add,
handle_owners_delete, handle_owners_list, handle_publish, handle_sparse_index, handle_unyank,
handle_yank,
};
use crate::index::IndexEntry;
use crate::owners::Owner;
#[derive(Debug, Clone, Default)]
pub struct CrateRecord {
pub entries: Vec<IndexEntry>,
pub tarballs: BTreeMap<String, Digest>,
pub owners: Vec<Owner>,
}
#[derive(Clone)]
pub struct CargoState {
pub blobs: Arc<dyn BlobStore>,
pub crates: Arc<RwLock<BTreeMap<String, CrateRecord>>>,
pub config: Arc<IndexConfig>,
}
impl CargoState {
#[must_use]
pub fn new(blobs: Arc<dyn BlobStore>, api_host: impl Into<String>) -> Self {
Self {
blobs,
crates: Arc::new(RwLock::new(BTreeMap::new())),
config: Arc::new(IndexConfig::new(api_host)),
}
}
}
pub fn router(state: CargoState) -> Router {
Router::new()
.route("/config.json", get(handle_config_json))
.route("/index/{*path}", get(handle_sparse_index))
.route("/index.git/{*path}", get(handle_git_index_stub))
.route("/api/v1/crates/new", put(handle_publish))
.route(
"/api/v1/crates/{name}/{version}/download",
get(handle_download),
)
.route("/api/v1/crates/{name}/{version}/yank", delete(handle_yank))
.route("/api/v1/crates/{name}/{version}/unyank", put(handle_unyank))
.route(
"/api/v1/crates/{name}/owners",
get(handle_owners_list)
.put(handle_owners_add)
.delete(handle_owners_delete),
)
.with_state(state)
}