use std::collections::HashSet;
use crate::{
Result,
api::ApiClient,
types::{ComponentType, InstalledComponent, StoreEntry},
};
use super::IdLookup;
pub(crate) fn partition_components(
components: Vec<InstalledComponent>,
) -> (Vec<InstalledComponent>, Vec<InstalledComponent>) {
components
.into_iter()
.partition(|c| c.component_type.registry_only())
}
pub(crate) fn fetch_store_entries(
client: &ApiClient,
regular_components: &[InstalledComponent],
lookup: &IdLookup,
) -> Result<Vec<StoreEntry>> {
if regular_components.is_empty() {
return Ok(Vec::new());
}
let known_ids: HashSet<u64> = regular_components
.iter()
.filter_map(|c| resolve_id_locally(c, lookup))
.collect();
let types = distinct_types(regular_components);
let catalog_entries = client.fetch_all(&types)?;
let catalog_ids: HashSet<u64> = catalog_entries.iter().map(|e| e.id).collect();
let missing_ids: Vec<u64> = known_ids
.iter()
.copied()
.filter(|id| !catalog_ids.contains(id))
.collect();
let targeted_entries: Vec<StoreEntry> = if !missing_ids.is_empty() {
client
.fetch_details(&missing_ids)
.into_iter()
.filter_map(|r| r.ok())
.collect()
} else {
Vec::new()
};
Ok(catalog_entries
.into_iter()
.chain(targeted_entries)
.collect())
}
fn resolve_id_locally(component: &InstalledComponent, lookup: &IdLookup) -> Option<u64> {
lookup
.registry_id_cache
.get(&component.directory_name)
.copied()
.or_else(|| {
lookup
.widgets_id_table
.get(&component.directory_name)
.copied()
})
}
fn distinct_types(components: &[InstalledComponent]) -> Vec<ComponentType> {
let mut seen = HashSet::new();
components
.iter()
.map(|c| c.component_type)
.filter(|t| seen.insert(*t))
.collect()
}