mod entity_search;
#[cfg(feature = "search")]
mod index;
pub use entity_search::{EntitySearch, EntitySearchResult};
#[cfg(feature = "search")]
pub use index::SearchIndex;
#[cfg(not(feature = "search"))]
mod stub_index {
use std::sync::Arc;
use crate::core::item::AnyItem;
pub struct SearchIndex;
impl SearchIndex {
pub fn new() -> Self {
Self
}
pub fn index_item(&self, _item: &Arc<dyn AnyItem>) {}
pub fn remove_entity(&self, _entity_id: &str) {}
pub fn commit(&self) {}
pub fn search(&self, _entity_type: &str, _query: &str, _limit: usize) -> Vec<Arc<str>> {
Vec::new()
}
pub fn is_searchable(&self, _entity_type: &str) -> bool {
false
}
pub fn build_from_registry(&self, _registry: &crate::store::StoreRegistry) {}
}
impl Default for SearchIndex {
fn default() -> Self {
Self::new()
}
}
}
use serde_json::Value;
#[cfg(not(feature = "search"))]
pub use stub_index::SearchIndex;
pub struct SearchableRegistration {
pub entity_type: &'static str,
pub fields: &'static [&'static str],
}
inventory::collect!(SearchableRegistration);
pub fn iter_searchable() -> impl Iterator<Item = &'static SearchableRegistration> {
inventory::iter::<SearchableRegistration>()
}
pub fn extract_searchable_text(item: &Value, fields: &[&str]) -> String {
let Some(obj) = item.as_object() else {
return String::new();
};
fields
.iter()
.filter_map(|field| {
obj.get(*field).and_then(|v| match v {
Value::String(s) => Some(s.as_str()),
Value::Number(n) => Some(n.to_string()).map(|s| s.leak() as &str),
Value::Bool(b) => Some(if *b { "true" } else { "false" }),
_ => None,
})
})
.collect::<Vec<_>>()
.join(" ")
}
#[cfg(test)]
mod tests {
use serde_json::json;
use super::*;
#[test]
fn test_extract_searchable_text() {
let item = json!({
"name": "Test Target",
"category": "Audio",
"serviceId": "svc-123"
});
let text = extract_searchable_text(&item, &["name", "category"]);
assert_eq!(text, "Test Target Audio");
}
#[test]
fn test_extract_searchable_text_missing_fields() {
let item = json!({
"name": "Test Target"
});
let text = extract_searchable_text(&item, &["name", "category"]);
assert_eq!(text, "Test Target");
}
}