use super::*;
pub(crate) fn has_version_query(query: Option<&str>) -> bool {
query.is_some_and(|q| q.split('&').any(|kv| kv.starts_with("v=")))
}
pub(crate) fn dep_cache_control(versioned: bool) -> &'static str {
if versioned {
"max-age=31536000,immutable"
} else {
"no-cache"
}
}
pub(crate) fn dep_response(headers: &HeaderMap, versioned: bool, bytes: Vec<u8>) -> Response {
let etag = format!("\"{}\"", &blake3::hash(&bytes).to_hex()[..16]);
let cache_control = dep_cache_control(versioned).to_string();
if headers
.get(header::IF_NONE_MATCH)
.and_then(|v| v.to_str().ok())
.is_some_and(|inm| inm.split(',').any(|t| t.trim() == etag))
{
return (
StatusCode::NOT_MODIFIED,
[(header::ETAG, etag), (header::CACHE_CONTROL, cache_control)],
)
.into_response();
}
(
[
(header::CONTENT_TYPE, "text/javascript".to_string()),
(header::CACHE_CONTROL, cache_control),
(header::ETAG, etag),
],
bytes,
)
.into_response()
}
pub(crate) const OPTIONAL_PEER_PREFIX: &str = "/@oj-optional-peer/";
pub(crate) fn optional_peer_dep_url(root: &Path, dir: &Path, spec: &str) -> Option<String> {
if !is_bare_specifier(spec) || spec.is_empty() || is_node_builtin(spec) || spec.contains('\0') {
return None;
}
let dir = std::fs::canonicalize(dir).unwrap_or_else(|_| dir.to_path_buf());
let root = std::fs::canonicalize(root).unwrap_or_else(|_| root.to_path_buf());
if dir == root || !in_node_modules(&dir) {
return None;
}
let pkg_name = {
let mut it = spec.split('/');
let first = it.next()?;
if first.starts_with('@') {
format!("{first}/{}", it.next()?)
} else {
first.to_string()
}
};
let mut cur: Option<&Path> = Some(dir.as_path());
while let Some(d) = cur {
if let Ok(txt) = std::fs::read_to_string(d.join("package.json")) {
if let Ok(pkg) = serde_json::from_str::<serde_json::Value>(&txt) {
if let Some(parent) = pkg.get("name").and_then(|n| n.as_str()) {
let declared = pkg
.get("peerDependencies")
.and_then(|p| p.get(&pkg_name))
.is_some();
let optional = pkg
.get("peerDependenciesMeta")
.and_then(|m| m.get(&pkg_name))
.and_then(|m| m.get("optional"))
.and_then(|o| o.as_bool())
.unwrap_or(false);
if declared && optional {
return Some(format!(
"{OPTIONAL_PEER_PREFIX}{}",
hex_encode(&format!("{spec}\n{parent}"))
));
}
return None;
}
}
}
if d.file_name().is_some_and(|n| n == "node_modules") {
return None;
}
cur = d.parent();
}
None
}
pub(crate) fn optional_peer_dep_stub(hex: &str) -> Option<String> {
let decoded = hex_decode(hex)?;
let (peer, parent) = decoded.split_once('\n')?;
let peer_js = serde_json::Value::String(peer.to_string());
let parent_js = serde_json::Value::String(parent.to_string());
Some(format!(
"// oj: optional peer dependency {peer_js} of {parent_js} is not installed\n\
export default {{}};\n\
export const __cjs_exports = {{}};\n\
throw new Error(`Could not resolve \"${{{peer_js}}}\" imported by \"${{{parent_js}}}\". Is it installed?`);\n"
))
}