use crate::error::{DumplingError, Result};
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
#[derive(Debug, Deserialize, Serialize)]
pub struct ImportMap {
pub imports: HashMap<String, String>,
#[serde(rename = "scopes")]
pub scopes: Option<HashMap<String, HashMap<String, String>>>,
}
impl ImportMap {
pub fn load(path: &PathBuf) -> Result<Self> {
let content = std::fs::read_to_string(path)?;
let import_map: ImportMap = serde_json::from_str(&content)
.map_err(|e| DumplingError::Build(format!("Invalid import map: {}", e)))?;
Ok(import_map)
}
pub fn resolve(&self, specifier: &str) -> Option<String> {
if let Some(resolved) = self.imports.get(specifier) {
return Some(resolved.clone());
}
for (key, value) in &self.imports {
if key.ends_with('/') && specifier.starts_with(key) {
let subpath = specifier.trim_start_matches(key);
return Some(format!("{}{}", value, subpath));
}
}
None
}
}
pub struct ImportMapResolver {
import_map: Option<ImportMap>,
}
impl ImportMapResolver {
pub fn new(root: &PathBuf) -> Self {
let import_map_path = root.join("importmap.json");
let import_map = if import_map_path.exists() {
Some(ImportMap::load(&import_map_path).unwrap_or_else(|_| {
println!(
"Warning: Failed to load import map from {}",
import_map_path.display()
);
ImportMap {
imports: HashMap::new(),
scopes: None,
}
}))
} else {
None
};
Self { import_map }
}
pub fn resolve(&self, specifier: &str) -> Option<String> {
if let Some(ref import_map) = self.import_map {
import_map.resolve(specifier)
} else {
None
}
}
}