diff options
author | David Sherret <dsherret@users.noreply.github.com> | 2023-04-06 18:46:44 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-06 18:46:44 -0400 |
commit | d07aa4a0723b04583b7cb1e09152457d866d13d3 (patch) | |
tree | f329a30becca95583fb71b4158c939c68228ce06 /cli/args | |
parent | 1586c52b5b5ad511ec0bf896e94de8585f743cf8 (diff) |
refactor(npm): use deno_npm and deno_semver (#18602)
Diffstat (limited to 'cli/args')
-rw-r--r-- | cli/args/lockfile.rs | 100 | ||||
-rw-r--r-- | cli/args/mod.rs | 11 | ||||
-rw-r--r-- | cli/args/package_json.rs | 37 |
3 files changed, 91 insertions, 57 deletions
diff --git a/cli/args/lockfile.rs b/cli/args/lockfile.rs index 1a3233c5a..31519aee3 100644 --- a/cli/args/lockfile.rs +++ b/cli/args/lockfile.rs @@ -1,18 +1,30 @@ // Copyright 2018-2023 the Deno authors. All rights reserved. MIT license. -use deno_core::error::AnyError; + +use std::collections::HashMap; use std::path::PathBuf; +use std::sync::Arc; + +use deno_core::anyhow::bail; +use deno_core::anyhow::Context; +use deno_core::error::AnyError; +use deno_core::futures::stream::FuturesOrdered; +use deno_core::futures::StreamExt; +use deno_core::parking_lot::Mutex; +use deno_npm::registry::NpmRegistryApi; +use deno_npm::resolution::NpmResolutionSnapshot; +use deno_npm::resolution::NpmResolutionSnapshotCreateOptions; +use deno_npm::resolution::NpmResolutionSnapshotCreateOptionsPackage; +use deno_npm::NpmPackageId; +use deno_semver::npm::NpmPackageReq; use crate::args::config_file::LockConfig; use crate::args::ConfigFile; -use crate::npm::NpmResolutionPackage; use crate::Flags; use super::DenoSubcommand; pub use deno_lockfile::Lockfile; pub use deno_lockfile::LockfileError; -use deno_lockfile::NpmPackageDependencyLockfileInfo; -use deno_lockfile::NpmPackageLockfileInfo; pub fn discover( flags: &Flags, @@ -61,24 +73,68 @@ pub fn discover( Ok(Some(lockfile)) } -// NOTE(bartlomieju): we don't want a reverse mapping to be possible. -#[allow(clippy::from_over_into)] -impl Into<NpmPackageLockfileInfo> for NpmResolutionPackage { - fn into(self) -> NpmPackageLockfileInfo { - let dependencies = self - .dependencies - .into_iter() - .map(|(name, id)| NpmPackageDependencyLockfileInfo { - name, - id: id.as_serialized(), - }) - .collect(); - - NpmPackageLockfileInfo { - display_id: self.pkg_id.nv.to_string(), - serialized_id: self.pkg_id.as_serialized(), - integrity: self.dist.integrity().to_string(), - dependencies, +pub async fn snapshot_from_lockfile( + lockfile: Arc<Mutex<Lockfile>>, + api: &dyn NpmRegistryApi, +) -> Result<NpmResolutionSnapshot, AnyError> { + let (root_packages, mut packages) = { + let lockfile = lockfile.lock(); + + let mut root_packages = + HashMap::<NpmPackageReq, NpmPackageId>::with_capacity( + lockfile.content.npm.specifiers.len(), + ); + // collect the specifiers to version mappings + for (key, value) in &lockfile.content.npm.specifiers { + let package_req = NpmPackageReq::from_str(key) + .with_context(|| format!("Unable to parse npm specifier: {key}"))?; + let package_id = NpmPackageId::from_serialized(value)?; + root_packages.insert(package_req, package_id.clone()); + } + + // now fill the packages except for the dist information + let mut packages = Vec::with_capacity(lockfile.content.npm.packages.len()); + for (key, package) in &lockfile.content.npm.packages { + let pkg_id = NpmPackageId::from_serialized(key)?; + + // collect the dependencies + let mut dependencies = HashMap::with_capacity(package.dependencies.len()); + for (name, specifier) in &package.dependencies { + let dep_id = NpmPackageId::from_serialized(specifier)?; + dependencies.insert(name.clone(), dep_id); + } + + packages.push(NpmResolutionSnapshotCreateOptionsPackage { + pkg_id, + dist: Default::default(), // temporarily empty + dependencies, + }); } + (root_packages, packages) + }; + + // now that the lockfile is dropped, fetch the package version information + let mut version_infos = + FuturesOrdered::from_iter(packages.iter().map(|p| p.pkg_id.nv.clone()).map( + |nv| async move { + match api.package_version_info(&nv).await? { + Some(version_info) => Ok(version_info), + None => { + bail!("could not find '{}' specified in the lockfile. Maybe try again with --reload", nv); + } + } + }, + )); + + let mut i = 0; + while let Some(version_info) = version_infos.next().await { + packages[i].dist = version_info?.dist; + i += 1; } + + NpmResolutionSnapshot::from_packages(NpmResolutionSnapshotCreateOptions { + packages, + root_packages, + }) + .context("The lockfile is corrupt. You can recreate it with --lock-write") } diff --git a/cli/args/mod.rs b/cli/args/mod.rs index bbf3f7efb..20c382622 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -8,14 +8,14 @@ mod lockfile; pub mod package_json; pub use self::import_map::resolve_import_map_from_specifier; +use self::lockfile::snapshot_from_lockfile; use self::package_json::PackageJsonDeps; use ::import_map::ImportMap; use deno_core::resolve_url_or_path; -use deno_graph::npm::NpmPackageReqReference; +use deno_npm::resolution::NpmResolutionSnapshot; +use deno_semver::npm::NpmPackageReqReference; use indexmap::IndexMap; -use crate::npm::NpmRegistryApi; -use crate::npm::NpmResolutionSnapshot; pub use config_file::BenchConfig; pub use config_file::CompilerOptions; pub use config_file::ConfigFile; @@ -65,6 +65,7 @@ use std::sync::Arc; use crate::cache::DenoDir; use crate::file_fetcher::FileFetcher; use crate::npm::NpmProcessState; +use crate::npm::NpmRegistry; use crate::util::fs::canonicalize_path_maybe_not_exists; use crate::version; @@ -745,7 +746,7 @@ impl CliOptions { pub async fn resolve_npm_resolution_snapshot( &self, - api: &NpmRegistryApi, + api: &NpmRegistry, ) -> Result<Option<NpmResolutionSnapshot>, AnyError> { if let Some(state) = &*NPM_PROCESS_STATE { // TODO(bartlomieju): remove this clone @@ -755,7 +756,7 @@ impl CliOptions { if let Some(lockfile) = self.maybe_lock_file() { if !lockfile.lock().overwrite { return Ok(Some( - NpmResolutionSnapshot::from_lockfile(lockfile.clone(), api) + snapshot_from_lockfile(lockfile.clone(), api) .await .with_context(|| { format!( diff --git a/cli/args/package_json.rs b/cli/args/package_json.rs index 5975395bb..c4d4ce956 100644 --- a/cli/args/package_json.rs +++ b/cli/args/package_json.rs @@ -7,41 +7,18 @@ use std::path::PathBuf; use deno_core::anyhow::bail; use deno_core::error::AnyError; -use deno_graph::npm::NpmPackageReq; -use deno_graph::semver::NpmVersionReqSpecifierParseError; -use deno_graph::semver::VersionReq; +use deno_npm::registry::parse_dep_entry_name_and_raw_version; +use deno_npm::registry::PackageDepNpmSchemeValueParseError; use deno_runtime::deno_node::PackageJson; +use deno_semver::npm::NpmPackageReq; +use deno_semver::npm::NpmVersionReqSpecifierParseError; +use deno_semver::VersionReq; use thiserror::Error; -#[derive(Debug, Clone, Error, PartialEq, Eq, Hash)] -#[error("Could not find @ symbol in npm url '{value}'")] -pub struct PackageJsonDepNpmSchemeValueParseError { - pub value: String, -} - -/// Gets the name and raw version constraint taking into account npm -/// package aliases. -pub fn parse_dep_entry_name_and_raw_version<'a>( - key: &'a str, - value: &'a str, -) -> Result<(&'a str, &'a str), PackageJsonDepNpmSchemeValueParseError> { - if let Some(package_and_version) = value.strip_prefix("npm:") { - if let Some((name, version)) = package_and_version.rsplit_once('@') { - Ok((name, version)) - } else { - Err(PackageJsonDepNpmSchemeValueParseError { - value: value.to_string(), - }) - } - } else { - Ok((key, value)) - } -} - -#[derive(Debug, Error, Clone, Hash)] +#[derive(Debug, Error, Clone)] pub enum PackageJsonDepValueParseError { #[error(transparent)] - SchemeValue(#[from] PackageJsonDepNpmSchemeValueParseError), + SchemeValue(#[from] PackageDepNpmSchemeValueParseError), #[error(transparent)] Specifier(#[from] NpmVersionReqSpecifierParseError), #[error("Not implemented scheme '{scheme}'")] |