use std::collections::BTreeMap;
use super::super::types::RouteAssets;
use crate::build::types::BundleManifest;
pub(super) fn compute_route_assets(
route_path: &str,
source_file_map: Option<&BTreeMap<String, String>>,
bundle_manifest: Option<&BundleManifest>,
) -> Option<RouteAssets> {
let sfm = source_file_map?;
let bm = bundle_manifest?;
let source_key = sfm.get(route_path)?;
let entry = bm.entries.get(source_key)?;
let mut exclude = std::collections::HashSet::<&str>::new();
for s in &entry.scripts {
exclude.insert(s);
}
for s in &entry.styles {
exclude.insert(s);
}
for s in &entry.preload {
exclude.insert(s);
}
for s in &bm.template.js {
exclude.insert(s);
}
for s in &bm.template.css {
exclude.insert(s);
}
let mut prefetch = Vec::new();
for (key, other_entry) in &bm.entries {
if key == source_key {
continue;
}
for s in &other_entry.scripts {
if !exclude.contains(s.as_str()) && !prefetch.contains(s) {
prefetch.push(s.clone());
}
}
for s in &other_entry.styles {
if !exclude.contains(s.as_str()) && !prefetch.contains(s) {
prefetch.push(s.clone());
}
}
}
Some(RouteAssets {
styles: entry.styles.clone(),
scripts: entry.scripts.clone(),
preload: entry.preload.clone(),
prefetch,
})
}
#[cfg(test)]
mod tests {
use super::*;
use crate::build::types::{AssetFiles, EntryAssets};
#[test]
fn compute_route_assets_both_none() {
let result = compute_route_assets("/", None, None);
assert!(result.is_none());
}
#[test]
fn compute_route_assets_missing_source_file_map() {
let bm =
BundleManifest { entries: BTreeMap::new(), template: AssetFiles { js: vec![], css: vec![] } };
let result = compute_route_assets("/", None, Some(&bm));
assert!(result.is_none());
}
#[test]
fn compute_route_assets_missing_bundle_manifest() {
let mut sfm = BTreeMap::new();
sfm.insert("/".to_string(), "src/Home.tsx".to_string());
let result = compute_route_assets("/", Some(&sfm), None);
assert!(result.is_none());
}
#[test]
fn compute_route_assets_route_not_in_map() {
let sfm = BTreeMap::new(); let bm =
BundleManifest { entries: BTreeMap::new(), template: AssetFiles { js: vec![], css: vec![] } };
let result = compute_route_assets("/missing", Some(&sfm), Some(&bm));
assert!(result.is_none());
}
#[test]
fn compute_route_assets_source_key_not_in_entries() {
let mut sfm = BTreeMap::new();
sfm.insert("/".to_string(), "src/Home.tsx".to_string());
let bm = BundleManifest {
entries: BTreeMap::new(), template: AssetFiles { js: vec![], css: vec![] },
};
let result = compute_route_assets("/", Some(&sfm), Some(&bm));
assert!(result.is_none());
}
#[test]
fn compute_route_assets_two_routes_symmetric() {
let mut sfm = BTreeMap::new();
sfm.insert("/".to_string(), "src/Home.tsx".to_string());
sfm.insert("/dashboard/:user".to_string(), "src/Dashboard.tsx".to_string());
let home_entry = EntryAssets {
scripts: vec!["assets/home-abc.js".to_string()],
styles: vec!["assets/home-abc.css".to_string(), "assets/shared.css".to_string()],
preload: vec!["assets/shared-xyz.js".to_string()],
};
let dash_entry = EntryAssets {
scripts: vec!["assets/dash-def.js".to_string()],
styles: vec!["assets/dash-def.css".to_string(), "assets/shared.css".to_string()],
preload: vec!["assets/shared-xyz.js".to_string()],
};
let mut entries = BTreeMap::new();
entries.insert("src/Home.tsx".to_string(), home_entry);
entries.insert("src/Dashboard.tsx".to_string(), dash_entry);
let template = AssetFiles {
js: vec!["assets/main-tmpl.js".to_string()],
css: vec!["assets/main-tmpl.css".to_string()],
};
let bm = BundleManifest { entries, template };
let home = compute_route_assets("/", Some(&sfm), Some(&bm)).unwrap();
assert_eq!(home.scripts, vec!["assets/home-abc.js"]);
assert_eq!(home.styles, vec!["assets/home-abc.css", "assets/shared.css"]);
assert_eq!(home.preload, vec!["assets/shared-xyz.js"]);
assert!(home.prefetch.contains(&"assets/dash-def.js".to_string()));
assert!(home.prefetch.contains(&"assets/dash-def.css".to_string()));
assert!(!home.prefetch.contains(&"assets/shared.css".to_string()));
assert!(!home.prefetch.contains(&"assets/main-tmpl.js".to_string()));
assert!(!home.prefetch.contains(&"assets/main-tmpl.css".to_string()));
assert!(!home.prefetch.contains(&"assets/home-abc.js".to_string()));
let dash = compute_route_assets("/dashboard/:user", Some(&sfm), Some(&bm)).unwrap();
assert_eq!(dash.scripts, vec!["assets/dash-def.js"]);
assert_eq!(dash.styles, vec!["assets/dash-def.css", "assets/shared.css"]);
assert_eq!(dash.preload, vec!["assets/shared-xyz.js"]);
assert!(dash.prefetch.contains(&"assets/home-abc.js".to_string()));
assert!(dash.prefetch.contains(&"assets/home-abc.css".to_string()));
assert!(!dash.prefetch.contains(&"assets/shared.css".to_string()));
assert!(!dash.prefetch.contains(&"assets/main-tmpl.js".to_string()));
assert!(!dash.prefetch.contains(&"assets/dash-def.js".to_string()));
}
}