use std::{borrow::Cow, fs::File, io::Read as _, path::Path};
use anyhow::Context as _;
use anyhow::Result;
use base64::{Engine as _, prelude::BASE64_STANDARD};
use crate::{ManifestChunk, ViteManifest};
pub fn parse_manifest(vite_dist: &Path) -> anyhow::Result<ViteManifest<'static>> {
let file = File::open(vite_dist.join(".vite").join("manifest.json"))
.context("failed to open vite manifest")?;
let mut manifest: ViteManifest =
serde_json::from_reader(file).context("failed to parse vite manifest")?;
for chunk in manifest.clone().values() {
for css in chunk.css.as_ref() {
manifest.insert(
css.clone(),
ManifestChunk {
key: css.clone(),
file: css.clone(),
..Default::default()
},
);
}
}
for (key, chunk) in &mut manifest {
chunk.key.clone_from(key);
}
Ok(manifest)
}
pub fn read_manifest_chunk(vite_dist: &Path, chunk: &mut ManifestChunk) -> Result<()> {
let mut file = File::open(vite_dist.join(chunk.file.as_ref())).with_context(|| {
format!(
r#"failed to open vite chunk at "{path}""#,
path = chunk.file
)
})?;
let mut contents = Vec::new();
file.read_to_end(&mut contents).with_context(|| {
format!(
r#"failed to read vite chunk at "{path}""#,
path = chunk.file
)
})?;
chunk.hash = Cow::Owned({
let hash = blake3::hash(&contents);
BASE64_STANDARD.encode(hash.as_bytes())
});
chunk.contents = Cow::Owned(contents);
chunk.mime_type = mime_guess::from_path(chunk.file.as_ref())
.first_or_octet_stream()
.to_string()
.into();
Ok(())
}