diff options
Diffstat (limited to 'cli/npm/resolution/specifier.rs')
-rw-r--r-- | cli/npm/resolution/specifier.rs | 69 |
1 files changed, 67 insertions, 2 deletions
diff --git a/cli/npm/resolution/specifier.rs b/cli/npm/resolution/specifier.rs index 1a1590a2f..b832540bd 100644 --- a/cli/npm/resolution/specifier.rs +++ b/cli/npm/resolution/specifier.rs @@ -32,8 +32,12 @@ impl NpmPackageReference { } pub fn from_str(specifier: &str) -> Result<NpmPackageReference, AnyError> { + let original_text = specifier; let specifier = match specifier.strip_prefix("npm:") { - Some(s) => s, + Some(s) => { + // Strip leading slash, which might come from import map + s.strip_prefix('/').unwrap_or(s) + } None => { // don't allocate a string here and instead use a static string // because this is hit a lot when a url is not an npm specifier @@ -65,7 +69,12 @@ impl NpmPackageReference { let sub_path = if parts.len() == name_parts.len() { None } else { - Some(parts[name_part_len..].join("/")) + let sub_path = parts[name_part_len..].join("/"); + if sub_path.is_empty() { + None + } else { + Some(sub_path) + } }; if let Some(sub_path) = &sub_path { @@ -79,6 +88,14 @@ impl NpmPackageReference { } } + if name.is_empty() { + let msg = format!( + "Invalid npm specifier '{}'. Did not contain a package name.", + original_text + ); + return Err(generic_error(msg)); + } + Ok(NpmPackageReference { req: NpmPackageReq { name, version_req }, sub_path, @@ -631,6 +648,54 @@ mod tests { .to_string(), "Not a valid package: @package" ); + + // should parse leading slash + assert_eq!( + NpmPackageReference::from_str("npm:/@package/test/sub_path").unwrap(), + NpmPackageReference { + req: NpmPackageReq { + name: "@package/test".to_string(), + version_req: None, + }, + sub_path: Some("sub_path".to_string()), + } + ); + assert_eq!( + NpmPackageReference::from_str("npm:/test").unwrap(), + NpmPackageReference { + req: NpmPackageReq { + name: "test".to_string(), + version_req: None, + }, + sub_path: None, + } + ); + assert_eq!( + NpmPackageReference::from_str("npm:/test/").unwrap(), + NpmPackageReference { + req: NpmPackageReq { + name: "test".to_string(), + version_req: None, + }, + sub_path: None, + } + ); + + // should error for no name + assert_eq!( + NpmPackageReference::from_str("npm:/") + .err() + .unwrap() + .to_string(), + "Invalid npm specifier 'npm:/'. Did not contain a package name." + ); + assert_eq!( + NpmPackageReference::from_str("npm://test") + .err() + .unwrap() + .to_string(), + "Invalid npm specifier 'npm://test'. Did not contain a package name." + ); } #[test] |