use std::collections::HashMap;
use nu_protocol::engine::{EngineState, StateWorkingSet, VirtualPath};
use crate::store::Store;
pub fn load_modules(
engine_state: &mut EngineState,
store: &Store,
modules: &HashMap<String, ssri::Integrity>,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
for (topic, hash) in modules {
let name = match topic.strip_suffix(".nu") {
Some(n) if !n.is_empty() => n,
_ => continue,
};
let content_bytes = store.cas_read_sync(hash)?;
let content = String::from_utf8(content_bytes)?;
register_module(engine_state, name, &content)?;
}
Ok(())
}
fn register_module(
engine_state: &mut EngineState,
name: &str,
content: &str,
) -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
let module_path = name.replace('.', "/");
let mut working_set = StateWorkingSet::new(engine_state);
let virt_file_name = format!("{module_path}/mod.nu");
let file_id = working_set.add_file(virt_file_name.clone(), content.as_bytes());
let virt_file_id = working_set.add_virtual_path(virt_file_name, VirtualPath::File(file_id));
let segments: Vec<&str> = module_path.split('/').collect();
let mut child_id = virt_file_id;
for depth in (0..segments.len()).rev() {
let dir_path = if depth == 0 {
segments[0].to_string()
} else {
segments[..=depth].join("/")
};
child_id = working_set.add_virtual_path(dir_path, VirtualPath::Dir(vec![child_id]));
}
engine_state.merge_delta(working_set.render())?;
tracing::debug!("Registered VFS module: {}", module_path);
Ok(())
}