mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
refactor(ext/node): remove dependency on deno_npm and deno_semver (#20718)
This is required from BYONM (bring your own node_modules). Part of #18967
This commit is contained in:
parent
0bd53fd52d
commit
d43e48c4e9
25 changed files with 360 additions and 263 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1526,8 +1526,6 @@ dependencies = [
|
||||||
"deno_fs",
|
"deno_fs",
|
||||||
"deno_media_type",
|
"deno_media_type",
|
||||||
"deno_net",
|
"deno_net",
|
||||||
"deno_npm",
|
|
||||||
"deno_semver 0.5.1",
|
|
||||||
"digest 0.10.7",
|
"digest 0.10.7",
|
||||||
"dsa",
|
"dsa",
|
||||||
"ecb",
|
"ecb",
|
||||||
|
|
|
@ -48,8 +48,6 @@ deno_bench_util = { version = "0.114.0", path = "./bench_util" }
|
||||||
test_util = { path = "./test_util" }
|
test_util = { path = "./test_util" }
|
||||||
deno_lockfile = "0.17.1"
|
deno_lockfile = "0.17.1"
|
||||||
deno_media_type = { version = "0.1.1", features = ["module_specifier"] }
|
deno_media_type = { version = "0.1.1", features = ["module_specifier"] }
|
||||||
deno_npm = "0.15.1"
|
|
||||||
deno_semver = "0.5.0"
|
|
||||||
|
|
||||||
# exts
|
# exts
|
||||||
deno_broadcast_channel = { version = "0.114.0", path = "./ext/broadcast_channel" }
|
deno_broadcast_channel = { version = "0.114.0", path = "./ext/broadcast_channel" }
|
||||||
|
|
|
@ -54,9 +54,9 @@ deno_emit = "=0.28.0"
|
||||||
deno_graph = "=0.55.0"
|
deno_graph = "=0.55.0"
|
||||||
deno_lint = { version = "=0.51.0", features = ["docs"] }
|
deno_lint = { version = "=0.51.0", features = ["docs"] }
|
||||||
deno_lockfile.workspace = true
|
deno_lockfile.workspace = true
|
||||||
deno_npm.workspace = true
|
deno_npm = "0.15.1"
|
||||||
deno_runtime = { workspace = true, features = ["dont_create_runtime_snapshot", "exclude_runtime_main_js", "include_js_files_for_snapshotting"] }
|
deno_runtime = { workspace = true, features = ["dont_create_runtime_snapshot", "exclude_runtime_main_js", "include_js_files_for_snapshotting"] }
|
||||||
deno_semver.workspace = true
|
deno_semver = "0.5.1"
|
||||||
deno_task_shell = "=0.13.2"
|
deno_task_shell = "=0.13.2"
|
||||||
eszip = "=0.53.0"
|
eszip = "=0.53.0"
|
||||||
napi_sym.workspace = true
|
napi_sym.workspace = true
|
||||||
|
|
|
@ -623,10 +623,11 @@ impl CliFactory {
|
||||||
&self,
|
&self,
|
||||||
) -> Result<CliMainWorkerFactory, AnyError> {
|
) -> Result<CliMainWorkerFactory, AnyError> {
|
||||||
let node_resolver = self.node_resolver().await?;
|
let node_resolver = self.node_resolver().await?;
|
||||||
|
let npm_resolver = self.npm_resolver().await?;
|
||||||
let fs = self.fs();
|
let fs = self.fs();
|
||||||
Ok(CliMainWorkerFactory::new(
|
Ok(CliMainWorkerFactory::new(
|
||||||
StorageKeyResolver::from_options(&self.options),
|
StorageKeyResolver::from_options(&self.options),
|
||||||
self.npm_resolver().await?.clone(),
|
npm_resolver.clone(),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
self.blob_store().clone(),
|
self.blob_store().clone(),
|
||||||
Box::new(CliModuleLoaderFactory::new(
|
Box::new(CliModuleLoaderFactory::new(
|
||||||
|
@ -641,6 +642,7 @@ impl CliFactory {
|
||||||
self.node_code_translator().await?.clone(),
|
self.node_code_translator().await?.clone(),
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
|
npm_resolver.clone(),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
self.root_cert_store_provider().clone(),
|
self.root_cert_store_provider().clone(),
|
||||||
|
|
|
@ -199,9 +199,8 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.npm_resolver.in_npm_package(specifier) {
|
if self.npm_resolver.in_npm_package(specifier) {
|
||||||
if let Ok(Some(pkg_id)) = self
|
if let Ok(Some(pkg_id)) =
|
||||||
.npm_resolver
|
self.npm_resolver.resolve_pkg_id_from_specifier(specifier)
|
||||||
.resolve_package_id_from_specifier(specifier)
|
|
||||||
{
|
{
|
||||||
let pkg_reqs =
|
let pkg_reqs =
|
||||||
self.npm_resolution.resolve_pkg_reqs_from_pkg_id(&pkg_id);
|
self.npm_resolution.resolve_pkg_reqs_from_pkg_id(&pkg_id);
|
||||||
|
@ -254,7 +253,7 @@ impl<'a> TsResponseImportMapper<'a> {
|
||||||
let specifier_path = specifier.to_file_path().ok()?;
|
let specifier_path = specifier.to_file_path().ok()?;
|
||||||
let root_folder = self
|
let root_folder = self
|
||||||
.npm_resolver
|
.npm_resolver
|
||||||
.resolve_package_folder_from_specifier(specifier)
|
.resolve_pkg_folder_from_specifier(specifier)
|
||||||
.ok()
|
.ok()
|
||||||
.flatten()?;
|
.flatten()?;
|
||||||
let package_json_path = root_folder.join("package.json");
|
let package_json_path = root_folder.join("package.json");
|
||||||
|
|
|
@ -800,8 +800,8 @@ fn generate_lint_diagnostics(
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore any npm package files
|
// ignore any npm package files
|
||||||
if let Some(node_resolver) = &snapshot.maybe_node_resolver {
|
if let Some(npm) = &snapshot.npm {
|
||||||
if node_resolver.in_npm_package(document.specifier()) {
|
if npm.node_resolver.in_npm_package(document.specifier()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1237,10 +1237,10 @@ fn diagnose_resolution(
|
||||||
} else if let Ok(pkg_ref) =
|
} else if let Ok(pkg_ref) =
|
||||||
NpmPackageReqReference::from_specifier(specifier)
|
NpmPackageReqReference::from_specifier(specifier)
|
||||||
{
|
{
|
||||||
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
|
if let Some(npm) = &snapshot.npm {
|
||||||
// show diagnostics for npm package references that aren't cached
|
// show diagnostics for npm package references that aren't cached
|
||||||
let req = pkg_ref.into_inner().req;
|
let req = pkg_ref.into_inner().req;
|
||||||
if !npm_resolver.is_pkg_req_folder_cached(&req) {
|
if !npm.npm_resolver.is_pkg_req_folder_cached(&req) {
|
||||||
diagnostics
|
diagnostics
|
||||||
.push(DenoDiagnostic::NoCacheNpm(req, specifier.clone()));
|
.push(DenoDiagnostic::NoCacheNpm(req, specifier.clone()));
|
||||||
}
|
}
|
||||||
|
@ -1250,10 +1250,10 @@ fn diagnose_resolution(
|
||||||
if !deno_node::is_builtin_node_module(module_name) {
|
if !deno_node::is_builtin_node_module(module_name) {
|
||||||
diagnostics
|
diagnostics
|
||||||
.push(DenoDiagnostic::InvalidNodeSpecifier(specifier.clone()));
|
.push(DenoDiagnostic::InvalidNodeSpecifier(specifier.clone()));
|
||||||
} else if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
|
} else if let Some(npm) = &snapshot.npm {
|
||||||
// check that a @types/node package exists in the resolver
|
// check that a @types/node package exists in the resolver
|
||||||
let types_node_req = PackageReq::from_str("@types/node").unwrap();
|
let types_node_req = PackageReq::from_str("@types/node").unwrap();
|
||||||
if !npm_resolver.is_pkg_req_folder_cached(&types_node_req) {
|
if !npm.npm_resolver.is_pkg_req_folder_cached(&types_node_req) {
|
||||||
diagnostics.push(DenoDiagnostic::NoCacheNpm(
|
diagnostics.push(DenoDiagnostic::NoCacheNpm(
|
||||||
types_node_req,
|
types_node_req,
|
||||||
ModuleSpecifier::parse("npm:@types/node").unwrap(),
|
ModuleSpecifier::parse("npm:@types/node").unwrap(),
|
||||||
|
@ -1291,8 +1291,8 @@ fn diagnose_dependency(
|
||||||
dependency_key: &str,
|
dependency_key: &str,
|
||||||
dependency: &deno_graph::Dependency,
|
dependency: &deno_graph::Dependency,
|
||||||
) {
|
) {
|
||||||
if let Some(npm_resolver) = &snapshot.maybe_npm_resolver {
|
if let Some(npm) = &snapshot.npm {
|
||||||
if npm_resolver.in_npm_package(referrer) {
|
if npm.npm_resolver.in_npm_package(referrer) {
|
||||||
return; // ignore, surface typescript errors instead
|
return; // ignore, surface typescript errors instead
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1461,8 +1461,7 @@ mod tests {
|
||||||
GlobalHttpCache::new(location.to_path_buf(), RealDenoCacheEnv),
|
GlobalHttpCache::new(location.to_path_buf(), RealDenoCacheEnv),
|
||||||
)),
|
)),
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
maybe_node_resolver: None,
|
npm: None,
|
||||||
maybe_npm_resolver: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use super::cache::calculate_fs_version;
|
use super::cache::calculate_fs_version;
|
||||||
use super::cache::calculate_fs_version_at_path;
|
use super::cache::calculate_fs_version_at_path;
|
||||||
|
use super::language_server::StateNpmSnapshot;
|
||||||
use super::text::LineIndex;
|
use super::text::LineIndex;
|
||||||
use super::tsc;
|
use super::tsc;
|
||||||
use super::tsc::AssetDocument;
|
use super::tsc::AssetDocument;
|
||||||
|
@ -41,7 +42,6 @@ use deno_graph::Resolution;
|
||||||
use deno_runtime::deno_node;
|
use deno_runtime::deno_node;
|
||||||
use deno_runtime::deno_node::NodeResolution;
|
use deno_runtime::deno_node::NodeResolution;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_runtime::permissions::PermissionsContainer;
|
use deno_runtime::permissions::PermissionsContainer;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
|
@ -1089,7 +1089,7 @@ impl Documents {
|
||||||
&self,
|
&self,
|
||||||
specifiers: Vec<String>,
|
specifiers: Vec<String>,
|
||||||
referrer_doc: &AssetOrDocument,
|
referrer_doc: &AssetOrDocument,
|
||||||
maybe_node_resolver: Option<&Arc<NodeResolver>>,
|
maybe_npm: Option<&StateNpmSnapshot>,
|
||||||
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
|
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
|
||||||
let referrer = referrer_doc.specifier();
|
let referrer = referrer_doc.specifier();
|
||||||
let dependencies = match referrer_doc {
|
let dependencies = match referrer_doc {
|
||||||
|
@ -1098,11 +1098,12 @@ impl Documents {
|
||||||
};
|
};
|
||||||
let mut results = Vec::new();
|
let mut results = Vec::new();
|
||||||
for specifier in specifiers {
|
for specifier in specifiers {
|
||||||
if let Some(node_resolver) = maybe_node_resolver {
|
if let Some(npm) = maybe_npm {
|
||||||
if node_resolver.in_npm_package(referrer) {
|
if npm.node_resolver.in_npm_package(referrer) {
|
||||||
// we're in an npm package, so use node resolution
|
// we're in an npm package, so use node resolution
|
||||||
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver
|
npm
|
||||||
|
.node_resolver
|
||||||
.resolve(
|
.resolve(
|
||||||
&specifier,
|
&specifier,
|
||||||
referrer,
|
referrer,
|
||||||
|
@ -1126,9 +1127,9 @@ impl Documents {
|
||||||
dependencies.as_ref().and_then(|d| d.deps.get(&specifier))
|
dependencies.as_ref().and_then(|d| d.deps.get(&specifier))
|
||||||
{
|
{
|
||||||
if let Some(specifier) = dep.maybe_type.maybe_specifier() {
|
if let Some(specifier) = dep.maybe_type.maybe_specifier() {
|
||||||
results.push(self.resolve_dependency(specifier, maybe_node_resolver));
|
results.push(self.resolve_dependency(specifier, maybe_npm));
|
||||||
} else if let Some(specifier) = dep.maybe_code.maybe_specifier() {
|
} else if let Some(specifier) = dep.maybe_code.maybe_specifier() {
|
||||||
results.push(self.resolve_dependency(specifier, maybe_node_resolver));
|
results.push(self.resolve_dependency(specifier, maybe_npm));
|
||||||
} else {
|
} else {
|
||||||
results.push(None);
|
results.push(None);
|
||||||
}
|
}
|
||||||
|
@ -1136,12 +1137,11 @@ impl Documents {
|
||||||
.resolve_imports_dependency(&specifier)
|
.resolve_imports_dependency(&specifier)
|
||||||
.and_then(|r| r.maybe_specifier())
|
.and_then(|r| r.maybe_specifier())
|
||||||
{
|
{
|
||||||
results.push(self.resolve_dependency(specifier, maybe_node_resolver));
|
results.push(self.resolve_dependency(specifier, maybe_npm));
|
||||||
} else if let Ok(npm_req_ref) =
|
} else if let Ok(npm_req_ref) =
|
||||||
NpmPackageReqReference::from_str(&specifier)
|
NpmPackageReqReference::from_str(&specifier)
|
||||||
{
|
{
|
||||||
results
|
results.push(node_resolve_npm_req_ref(npm_req_ref, maybe_npm));
|
||||||
.push(node_resolve_npm_req_ref(npm_req_ref, maybe_node_resolver));
|
|
||||||
} else {
|
} else {
|
||||||
results.push(None);
|
results.push(None);
|
||||||
}
|
}
|
||||||
|
@ -1475,7 +1475,7 @@ impl Documents {
|
||||||
fn resolve_dependency(
|
fn resolve_dependency(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
maybe_node_resolver: Option<&Arc<NodeResolver>>,
|
maybe_npm: Option<&StateNpmSnapshot>,
|
||||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||||
if let Some(module_name) = specifier.as_str().strip_prefix("node:") {
|
if let Some(module_name) = specifier.as_str().strip_prefix("node:") {
|
||||||
if deno_node::is_builtin_node_module(module_name) {
|
if deno_node::is_builtin_node_module(module_name) {
|
||||||
|
@ -1487,7 +1487,7 @@ impl Documents {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
||||||
return node_resolve_npm_req_ref(npm_ref, maybe_node_resolver);
|
return node_resolve_npm_req_ref(npm_ref, maybe_npm);
|
||||||
}
|
}
|
||||||
let doc = self.get(specifier)?;
|
let doc = self.get(specifier)?;
|
||||||
let maybe_module = doc.maybe_esm_module().and_then(|r| r.as_ref().ok());
|
let maybe_module = doc.maybe_esm_module().and_then(|r| r.as_ref().ok());
|
||||||
|
@ -1496,7 +1496,7 @@ impl Documents {
|
||||||
if let Some(specifier) =
|
if let Some(specifier) =
|
||||||
maybe_types_dependency.and_then(|d| d.maybe_specifier())
|
maybe_types_dependency.and_then(|d| d.maybe_specifier())
|
||||||
{
|
{
|
||||||
self.resolve_dependency(specifier, maybe_node_resolver)
|
self.resolve_dependency(specifier, maybe_npm)
|
||||||
} else {
|
} else {
|
||||||
let media_type = doc.media_type();
|
let media_type = doc.media_type();
|
||||||
Some((doc.specifier().clone(), media_type))
|
Some((doc.specifier().clone(), media_type))
|
||||||
|
@ -1519,18 +1519,26 @@ impl Documents {
|
||||||
|
|
||||||
fn node_resolve_npm_req_ref(
|
fn node_resolve_npm_req_ref(
|
||||||
npm_req_ref: NpmPackageReqReference,
|
npm_req_ref: NpmPackageReqReference,
|
||||||
maybe_node_resolver: Option<&Arc<NodeResolver>>,
|
maybe_npm: Option<&StateNpmSnapshot>,
|
||||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||||
maybe_node_resolver.map(|node_resolver| {
|
maybe_npm.map(|npm| {
|
||||||
NodeResolution::into_specifier_and_media_type(
|
NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver
|
npm
|
||||||
.resolve_npm_req_reference(
|
.npm_resolver
|
||||||
&npm_req_ref,
|
.resolve_pkg_folder_from_deno_module_req(npm_req_ref.req())
|
||||||
NodeResolutionMode::Types,
|
|
||||||
&PermissionsContainer::allow_all(),
|
|
||||||
)
|
|
||||||
.ok()
|
.ok()
|
||||||
.flatten(),
|
.and_then(|package_folder| {
|
||||||
|
npm
|
||||||
|
.node_resolver
|
||||||
|
.resolve_npm_reference(
|
||||||
|
&package_folder,
|
||||||
|
npm_req_ref.sub_path(),
|
||||||
|
NodeResolutionMode::Types,
|
||||||
|
&PermissionsContainer::allow_all(),
|
||||||
|
)
|
||||||
|
.ok()
|
||||||
|
.flatten()
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,6 +158,12 @@ impl LspNpmConfigHash {
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
|
pub struct LanguageServer(Arc<tokio::sync::RwLock<Inner>>);
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct StateNpmSnapshot {
|
||||||
|
pub node_resolver: Arc<NodeResolver>,
|
||||||
|
pub npm_resolver: Arc<CliNpmResolver>,
|
||||||
|
}
|
||||||
|
|
||||||
/// Snapshot of the state used by TSC.
|
/// Snapshot of the state used by TSC.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct StateSnapshot {
|
pub struct StateSnapshot {
|
||||||
|
@ -166,8 +172,7 @@ pub struct StateSnapshot {
|
||||||
pub config: Arc<ConfigSnapshot>,
|
pub config: Arc<ConfigSnapshot>,
|
||||||
pub documents: Documents,
|
pub documents: Documents,
|
||||||
pub maybe_import_map: Option<Arc<ImportMap>>,
|
pub maybe_import_map: Option<Arc<ImportMap>>,
|
||||||
pub maybe_node_resolver: Option<Arc<NodeResolver>>,
|
pub npm: Option<StateNpmSnapshot>,
|
||||||
pub maybe_npm_resolver: Option<Arc<CliNpmResolver>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -819,8 +824,10 @@ impl Inner {
|
||||||
config: self.config.snapshot(),
|
config: self.config.snapshot(),
|
||||||
documents: self.documents.clone(),
|
documents: self.documents.clone(),
|
||||||
maybe_import_map: self.maybe_import_map.clone(),
|
maybe_import_map: self.maybe_import_map.clone(),
|
||||||
maybe_node_resolver: Some(node_resolver),
|
npm: Some(StateNpmSnapshot {
|
||||||
maybe_npm_resolver: Some(npm_resolver),
|
node_resolver,
|
||||||
|
npm_resolver,
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3293,9 +3293,9 @@ fn op_is_node_file(state: &mut OpState, #[string] path: String) -> bool {
|
||||||
match ModuleSpecifier::parse(&path) {
|
match ModuleSpecifier::parse(&path) {
|
||||||
Ok(specifier) => state
|
Ok(specifier) => state
|
||||||
.state_snapshot
|
.state_snapshot
|
||||||
.maybe_npm_resolver
|
.npm
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|r| r.in_npm_package(&specifier))
|
.map(|n| n.npm_resolver.in_npm_package(&specifier))
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
|
@ -3341,7 +3341,7 @@ fn op_resolve(
|
||||||
let resolved = state.state_snapshot.documents.resolve(
|
let resolved = state.state_snapshot.documents.resolve(
|
||||||
args.specifiers,
|
args.specifiers,
|
||||||
&referrer_doc,
|
&referrer_doc,
|
||||||
state.state_snapshot.maybe_node_resolver.as_ref(),
|
state.state_snapshot.npm.as_ref(),
|
||||||
);
|
);
|
||||||
Ok(
|
Ok(
|
||||||
resolved
|
resolved
|
||||||
|
@ -3477,8 +3477,7 @@ deno_core::extension!(deno_tsc,
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
documents: Documents::new(options.cache.clone()),
|
documents: Documents::new(options.cache.clone()),
|
||||||
maybe_import_map: None,
|
maybe_import_map: None,
|
||||||
maybe_node_resolver: None,
|
npm: None,
|
||||||
maybe_npm_resolver: None,
|
|
||||||
}),
|
}),
|
||||||
options.performance,
|
options.performance,
|
||||||
));
|
));
|
||||||
|
@ -4304,8 +4303,7 @@ mod tests {
|
||||||
cache_metadata: CacheMetadata::new(cache),
|
cache_metadata: CacheMetadata::new(cache),
|
||||||
config: Default::default(),
|
config: Default::default(),
|
||||||
maybe_import_map: None,
|
maybe_import_map: None,
|
||||||
maybe_node_resolver: None,
|
npm: None,
|
||||||
maybe_npm_resolver: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@ use crate::graph_util::ModuleGraphBuilder;
|
||||||
use crate::graph_util::ModuleGraphContainer;
|
use crate::graph_util::ModuleGraphContainer;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
use crate::node::CliNodeCodeTranslator;
|
use crate::node::CliNodeCodeTranslator;
|
||||||
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::resolver::CliGraphResolver;
|
use crate::resolver::CliGraphResolver;
|
||||||
use crate::tools::check;
|
use crate::tools::check;
|
||||||
use crate::tools::check::TypeChecker;
|
use crate::tools::check::TypeChecker;
|
||||||
|
@ -646,6 +647,7 @@ pub struct NpmModuleLoader {
|
||||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
node_resolver: Arc<NodeResolver>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<CliNpmResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NpmModuleLoader {
|
impl NpmModuleLoader {
|
||||||
|
@ -654,12 +656,14 @@ impl NpmModuleLoader {
|
||||||
node_code_translator: Arc<CliNodeCodeTranslator>,
|
node_code_translator: Arc<CliNodeCodeTranslator>,
|
||||||
fs: Arc<dyn deno_fs::FileSystem>,
|
fs: Arc<dyn deno_fs::FileSystem>,
|
||||||
node_resolver: Arc<NodeResolver>,
|
node_resolver: Arc<NodeResolver>,
|
||||||
|
npm_resolver: Arc<CliNpmResolver>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
cjs_resolutions,
|
cjs_resolutions,
|
||||||
node_code_translator,
|
node_code_translator,
|
||||||
fs,
|
fs,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
|
npm_resolver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -693,9 +697,13 @@ impl NpmModuleLoader {
|
||||||
nv_ref: &NpmPackageNvReference,
|
nv_ref: &NpmPackageNvReference,
|
||||||
permissions: &PermissionsContainer,
|
permissions: &PermissionsContainer,
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
|
let package_folder = self
|
||||||
|
.npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module(nv_ref.nv())?;
|
||||||
self
|
self
|
||||||
.handle_node_resolve_result(self.node_resolver.resolve_npm_reference(
|
.handle_node_resolve_result(self.node_resolver.resolve_npm_reference(
|
||||||
nv_ref,
|
&package_folder,
|
||||||
|
nv_ref.sub_path(),
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
permissions,
|
permissions,
|
||||||
))
|
))
|
||||||
|
@ -704,16 +712,20 @@ impl NpmModuleLoader {
|
||||||
|
|
||||||
pub fn resolve_req_reference(
|
pub fn resolve_req_reference(
|
||||||
&self,
|
&self,
|
||||||
reference: &NpmPackageReqReference,
|
req_ref: &NpmPackageReqReference,
|
||||||
permissions: &PermissionsContainer,
|
permissions: &PermissionsContainer,
|
||||||
) -> Result<ModuleSpecifier, AnyError> {
|
) -> Result<ModuleSpecifier, AnyError> {
|
||||||
|
let package_folder = self
|
||||||
|
.npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module_req(req_ref.req())?;
|
||||||
self
|
self
|
||||||
.handle_node_resolve_result(self.node_resolver.resolve_npm_req_reference(
|
.handle_node_resolve_result(self.node_resolver.resolve_npm_reference(
|
||||||
reference,
|
&package_folder,
|
||||||
|
req_ref.sub_path(),
|
||||||
NodeResolutionMode::Execution,
|
NodeResolutionMode::Execution,
|
||||||
permissions,
|
permissions,
|
||||||
))
|
))
|
||||||
.with_context(|| format!("Could not resolve '{reference}'."))
|
.with_context(|| format!("Could not resolve '{}'.", req_ref))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_prepare_load(
|
pub fn maybe_prepare_load(
|
||||||
|
|
|
@ -105,7 +105,7 @@ impl PackageJsonDepsInstaller {
|
||||||
let (req, info) = result?;
|
let (req, info) = result?;
|
||||||
let result = inner
|
let result = inner
|
||||||
.npm_resolution
|
.npm_resolution
|
||||||
.resolve_package_req_as_pending_with_info(req, &info);
|
.resolve_pkg_req_as_pending_with_info(req, &info);
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
if inner.npm_registry_api.mark_force_reload() {
|
if inner.npm_registry_api.mark_force_reload() {
|
||||||
log::debug!("Failed to resolve package. Retrying. Error: {err:#}");
|
log::debug!("Failed to resolve package. Retrying. Error: {err:#}");
|
||||||
|
|
|
@ -224,19 +224,19 @@ impl NpmResolution {
|
||||||
/// Resolves a package requirement for deno graph. This should only be
|
/// Resolves a package requirement for deno graph. This should only be
|
||||||
/// called by deno_graph's NpmResolver or for resolving packages in
|
/// called by deno_graph's NpmResolver or for resolving packages in
|
||||||
/// a package.json
|
/// a package.json
|
||||||
pub fn resolve_package_req_as_pending(
|
pub fn resolve_pkg_req_as_pending(
|
||||||
&self,
|
&self,
|
||||||
pkg_req: &PackageReq,
|
pkg_req: &PackageReq,
|
||||||
) -> Result<PackageNv, NpmPackageVersionResolutionError> {
|
) -> Result<PackageNv, NpmPackageVersionResolutionError> {
|
||||||
// we should always have this because it should have been cached before here
|
// we should always have this because it should have been cached before here
|
||||||
let package_info = self.api.get_cached_package_info(&pkg_req.name).unwrap();
|
let package_info = self.api.get_cached_package_info(&pkg_req.name).unwrap();
|
||||||
self.resolve_package_req_as_pending_with_info(pkg_req, &package_info)
|
self.resolve_pkg_req_as_pending_with_info(pkg_req, &package_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Resolves a package requirement for deno graph. This should only be
|
/// Resolves a package requirement for deno graph. This should only be
|
||||||
/// called by deno_graph's NpmResolver or for resolving packages in
|
/// called by deno_graph's NpmResolver or for resolving packages in
|
||||||
/// a package.json
|
/// a package.json
|
||||||
pub fn resolve_package_req_as_pending_with_info(
|
pub fn resolve_pkg_req_as_pending_with_info(
|
||||||
&self,
|
&self,
|
||||||
pkg_req: &PackageReq,
|
pkg_req: &PackageReq,
|
||||||
package_info: &NpmPackageInfo,
|
package_info: &NpmPackageInfo,
|
||||||
|
|
|
@ -23,7 +23,10 @@ use deno_runtime::deno_fs::FileSystem;
|
||||||
use deno_runtime::deno_node::NodePermissions;
|
use deno_runtime::deno_node::NodePermissions;
|
||||||
use deno_runtime::deno_node::NodeResolutionMode;
|
use deno_runtime::deno_node::NodeResolutionMode;
|
||||||
use deno_runtime::deno_node::NpmResolver;
|
use deno_runtime::deno_node::NpmResolver;
|
||||||
|
use deno_semver::npm::NpmPackageNvReference;
|
||||||
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageNv;
|
use deno_semver::package::PackageNv;
|
||||||
|
use deno_semver::package::PackageNvReference;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use global::GlobalNpmPackageResolver;
|
use global::GlobalNpmPackageResolver;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -98,6 +101,19 @@ impl CliNpmResolver {
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_nv_ref_from_pkg_req_ref(
|
||||||
|
&self,
|
||||||
|
req_ref: &NpmPackageReqReference,
|
||||||
|
) -> Result<NpmPackageNvReference, PackageReqNotFoundError> {
|
||||||
|
let pkg_nv = self
|
||||||
|
.resolve_pkg_id_from_pkg_req(req_ref.req())
|
||||||
|
.map(|id| id.nv)?;
|
||||||
|
Ok(NpmPackageNvReference::new(PackageNvReference {
|
||||||
|
nv: pkg_nv,
|
||||||
|
sub_path: req_ref.sub_path().map(|s| s.to_string()),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
pub fn resolve_pkg_id_from_pkg_req(
|
pub fn resolve_pkg_id_from_pkg_req(
|
||||||
&self,
|
&self,
|
||||||
req: &PackageReq,
|
req: &PackageReq,
|
||||||
|
@ -127,7 +143,7 @@ impl CliNpmResolver {
|
||||||
/// Resolve the root folder of the package the provided specifier is in.
|
/// Resolve the root folder of the package the provided specifier is in.
|
||||||
///
|
///
|
||||||
/// This will error when the provided specifier is not in an npm package.
|
/// This will error when the provided specifier is not in an npm package.
|
||||||
pub fn resolve_package_folder_from_specifier(
|
pub fn resolve_pkg_folder_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<Option<PathBuf>, AnyError> {
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
|
@ -145,8 +161,24 @@ impl CliNpmResolver {
|
||||||
Ok(Some(path))
|
Ok(Some(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_folder_from_deno_module_req(
|
||||||
|
&self,
|
||||||
|
req: &PackageReq,
|
||||||
|
) -> Result<PathBuf, AnyError> {
|
||||||
|
let pkg_id = self.resolve_pkg_id_from_pkg_req(req)?;
|
||||||
|
self.resolve_pkg_folder_from_pkg_id(&pkg_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn resolve_pkg_folder_from_deno_module(
|
||||||
|
&self,
|
||||||
|
nv: &PackageNv,
|
||||||
|
) -> Result<PathBuf, AnyError> {
|
||||||
|
let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(nv)?;
|
||||||
|
self.resolve_pkg_folder_from_pkg_id(&pkg_id)
|
||||||
|
}
|
||||||
|
|
||||||
/// Resolves the package nv from the provided specifier.
|
/// Resolves the package nv from the provided specifier.
|
||||||
pub fn resolve_package_id_from_specifier(
|
pub fn resolve_pkg_id_from_specifier(
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<Option<NpmPackageId>, AnyError> {
|
) -> Result<Option<NpmPackageId>, AnyError> {
|
||||||
|
@ -266,22 +298,7 @@ impl NpmResolver for CliNpmResolver {
|
||||||
&self,
|
&self,
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<Option<PathBuf>, AnyError> {
|
) -> Result<Option<PathBuf>, AnyError> {
|
||||||
self.resolve_package_folder_from_specifier(specifier)
|
self.resolve_pkg_folder_from_specifier(specifier)
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_package_folder_from_deno_module(
|
|
||||||
&self,
|
|
||||||
pkg_nv: &PackageNv,
|
|
||||||
) -> Result<PathBuf, AnyError> {
|
|
||||||
let pkg_id = self.resolution.resolve_pkg_id_from_deno_module(pkg_nv)?;
|
|
||||||
self.resolve_pkg_folder_from_pkg_id(&pkg_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_pkg_id_from_pkg_req(
|
|
||||||
&self,
|
|
||||||
req: &PackageReq,
|
|
||||||
) -> Result<NpmPackageId, PackageReqNotFoundError> {
|
|
||||||
self.resolution.resolve_pkg_id_from_pkg_req(req)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||||
|
|
|
@ -319,9 +319,7 @@ impl NpmResolver for CliGraphResolver {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = self
|
let result = self.npm_resolution.resolve_pkg_req_as_pending(package_req);
|
||||||
.npm_resolution
|
|
||||||
.resolve_package_req_as_pending(package_req);
|
|
||||||
match result {
|
match result {
|
||||||
Ok(nv) => NpmPackageReqResolution::Ok(nv),
|
Ok(nv) => NpmPackageReqResolution::Ok(nv),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
|
|
@ -404,6 +404,7 @@ pub async fn run(
|
||||||
node_code_translator,
|
node_code_translator,
|
||||||
fs.clone(),
|
fs.clone(),
|
||||||
node_resolver.clone(),
|
node_resolver.clone(),
|
||||||
|
npm_resolver.clone(),
|
||||||
)),
|
)),
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
@ -429,7 +430,7 @@ pub async fn run(
|
||||||
};
|
};
|
||||||
let worker_factory = CliMainWorkerFactory::new(
|
let worker_factory = CliMainWorkerFactory::new(
|
||||||
StorageKeyResolver::empty(),
|
StorageKeyResolver::empty(),
|
||||||
npm_resolver.clone(),
|
npm_resolver,
|
||||||
node_resolver,
|
node_resolver,
|
||||||
Default::default(),
|
Default::default(),
|
||||||
Box::new(module_loader_factory),
|
Box::new(module_loader_factory),
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
error: package '@denotest/esm-basic' did not have a bin property in its package.json
|
error: '[WILDCARD]@denotest[WILDCARD]esm-basic[WILDCARD]package.json' did not have a bin property
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
error: package '@denotest/esm-basic' did not have a bin property in its package.json
|
error: '[WILDCARD]@denotest[WILDCARD]esm-basic[WILDCARD]package.json' did not have a bin property
|
||||||
|
|
||||||
Fallback failed: Cannot find module 'file:///[WILDCARD]/non-existent.js'
|
Fallback failed: Cannot find module 'file:///[WILDCARD]/non-existent.js'
|
||||||
|
|
|
@ -138,7 +138,10 @@ impl TypeChecker {
|
||||||
debug,
|
debug,
|
||||||
graph: graph.clone(),
|
graph: graph.clone(),
|
||||||
hash_data,
|
hash_data,
|
||||||
maybe_node_resolver: Some(self.node_resolver.clone()),
|
maybe_npm: Some(tsc::RequestNpmState {
|
||||||
|
node_resolver: self.node_resolver.clone(),
|
||||||
|
npm_resolver: self.npm_resolver.clone(),
|
||||||
|
}),
|
||||||
maybe_tsbuildinfo,
|
maybe_tsbuildinfo,
|
||||||
root_names,
|
root_names,
|
||||||
check_mode: type_check_mode,
|
check_mode: type_check_mode,
|
||||||
|
|
|
@ -268,7 +268,9 @@ fn resolve_npm_commands(
|
||||||
let mut result = HashMap::new();
|
let mut result = HashMap::new();
|
||||||
let snapshot = npm_resolver.snapshot();
|
let snapshot = npm_resolver.snapshot();
|
||||||
for id in snapshot.top_level_packages() {
|
for id in snapshot.top_level_packages() {
|
||||||
let bin_commands = node_resolver.resolve_binary_commands(&id.nv)?;
|
let package_folder = npm_resolver.resolve_pkg_folder_from_pkg_id(id)?;
|
||||||
|
let bin_commands =
|
||||||
|
node_resolver.resolve_binary_commands(&package_folder)?;
|
||||||
for bin_command in bin_commands {
|
for bin_command in bin_commands {
|
||||||
result.insert(
|
result.insert(
|
||||||
bin_command.to_string(),
|
bin_command.to_string(),
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::args::TsConfig;
|
||||||
use crate::args::TypeCheckMode;
|
use crate::args::TypeCheckMode;
|
||||||
use crate::cache::FastInsecureHasher;
|
use crate::cache::FastInsecureHasher;
|
||||||
use crate::node;
|
use crate::node;
|
||||||
|
use crate::npm::CliNpmResolver;
|
||||||
use crate::util::checksum;
|
use crate::util::checksum;
|
||||||
use crate::util::path::mapped_specifier_for_tsc;
|
use crate::util::path::mapped_specifier_for_tsc;
|
||||||
|
|
||||||
|
@ -293,6 +294,12 @@ pub struct EmittedFile {
|
||||||
pub media_type: MediaType,
|
pub media_type: MediaType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct RequestNpmState {
|
||||||
|
pub node_resolver: Arc<NodeResolver>,
|
||||||
|
pub npm_resolver: Arc<CliNpmResolver>,
|
||||||
|
}
|
||||||
|
|
||||||
/// A structure representing a request to be sent to the tsc runtime.
|
/// A structure representing a request to be sent to the tsc runtime.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Request {
|
pub struct Request {
|
||||||
|
@ -303,7 +310,7 @@ pub struct Request {
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
pub graph: Arc<ModuleGraph>,
|
pub graph: Arc<ModuleGraph>,
|
||||||
pub hash_data: u64,
|
pub hash_data: u64,
|
||||||
pub maybe_node_resolver: Option<Arc<NodeResolver>>,
|
pub maybe_npm: Option<RequestNpmState>,
|
||||||
pub maybe_tsbuildinfo: Option<String>,
|
pub maybe_tsbuildinfo: Option<String>,
|
||||||
/// A vector of strings that represent the root/entry point modules for the
|
/// A vector of strings that represent the root/entry point modules for the
|
||||||
/// program.
|
/// program.
|
||||||
|
@ -327,7 +334,7 @@ struct State {
|
||||||
graph: Arc<ModuleGraph>,
|
graph: Arc<ModuleGraph>,
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
maybe_response: Option<RespondArgs>,
|
maybe_response: Option<RespondArgs>,
|
||||||
maybe_node_resolver: Option<Arc<NodeResolver>>,
|
maybe_npm: Option<RequestNpmState>,
|
||||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||||
root_map: HashMap<String, ModuleSpecifier>,
|
root_map: HashMap<String, ModuleSpecifier>,
|
||||||
current_dir: PathBuf,
|
current_dir: PathBuf,
|
||||||
|
@ -340,7 +347,7 @@ impl Default for State {
|
||||||
graph: Arc::new(ModuleGraph::new(GraphKind::All)),
|
graph: Arc::new(ModuleGraph::new(GraphKind::All)),
|
||||||
maybe_tsbuildinfo: Default::default(),
|
maybe_tsbuildinfo: Default::default(),
|
||||||
maybe_response: Default::default(),
|
maybe_response: Default::default(),
|
||||||
maybe_node_resolver: Default::default(),
|
maybe_npm: Default::default(),
|
||||||
remapped_specifiers: Default::default(),
|
remapped_specifiers: Default::default(),
|
||||||
root_map: Default::default(),
|
root_map: Default::default(),
|
||||||
current_dir: Default::default(),
|
current_dir: Default::default(),
|
||||||
|
@ -352,7 +359,7 @@ impl State {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
graph: Arc<ModuleGraph>,
|
graph: Arc<ModuleGraph>,
|
||||||
hash_data: u64,
|
hash_data: u64,
|
||||||
maybe_node_resolver: Option<Arc<NodeResolver>>,
|
maybe_npm: Option<RequestNpmState>,
|
||||||
maybe_tsbuildinfo: Option<String>,
|
maybe_tsbuildinfo: Option<String>,
|
||||||
root_map: HashMap<String, ModuleSpecifier>,
|
root_map: HashMap<String, ModuleSpecifier>,
|
||||||
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
remapped_specifiers: HashMap<String, ModuleSpecifier>,
|
||||||
|
@ -361,7 +368,7 @@ impl State {
|
||||||
State {
|
State {
|
||||||
hash_data,
|
hash_data,
|
||||||
graph,
|
graph,
|
||||||
maybe_node_resolver,
|
maybe_npm,
|
||||||
maybe_tsbuildinfo,
|
maybe_tsbuildinfo,
|
||||||
maybe_response: None,
|
maybe_response: None,
|
||||||
remapped_specifiers,
|
remapped_specifiers,
|
||||||
|
@ -496,9 +503,9 @@ fn op_load(state: &mut OpState, args: Value) -> Result<Value, AnyError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if state
|
} else if state
|
||||||
.maybe_node_resolver
|
.maybe_npm
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|resolver| resolver.in_npm_package(specifier))
|
.map(|npm| npm.node_resolver.in_npm_package(specifier))
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
media_type = MediaType::from_specifier(specifier);
|
media_type = MediaType::from_specifier(specifier);
|
||||||
|
@ -650,9 +657,13 @@ fn resolve_graph_specifier_types(
|
||||||
Ok(Some((module.specifier.clone(), module.media_type)))
|
Ok(Some((module.specifier.clone(), module.media_type)))
|
||||||
}
|
}
|
||||||
Some(Module::Npm(module)) => {
|
Some(Module::Npm(module)) => {
|
||||||
if let Some(node_resolver) = &state.maybe_node_resolver {
|
if let Some(npm) = &state.maybe_npm {
|
||||||
let maybe_resolution = node_resolver.resolve_npm_reference(
|
let package_folder = npm
|
||||||
&module.nv_reference,
|
.npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module(module.nv_reference.nv())?;
|
||||||
|
let maybe_resolution = npm.node_resolver.resolve_npm_reference(
|
||||||
|
&package_folder,
|
||||||
|
module.nv_reference.sub_path(),
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
&PermissionsContainer::allow_all(),
|
&PermissionsContainer::allow_all(),
|
||||||
)?;
|
)?;
|
||||||
|
@ -665,11 +676,11 @@ fn resolve_graph_specifier_types(
|
||||||
}
|
}
|
||||||
Some(Module::External(module)) => {
|
Some(Module::External(module)) => {
|
||||||
// we currently only use "External" for when the module is in an npm package
|
// we currently only use "External" for when the module is in an npm package
|
||||||
Ok(state.maybe_node_resolver.as_ref().map(|node_resolver| {
|
Ok(state.maybe_npm.as_ref().map(|npm| {
|
||||||
let specifier =
|
let specifier =
|
||||||
node::resolve_specifier_into_node_modules(&module.specifier);
|
node::resolve_specifier_into_node_modules(&module.specifier);
|
||||||
NodeResolution::into_specifier_and_media_type(
|
NodeResolution::into_specifier_and_media_type(
|
||||||
node_resolver.url_to_node_resolution(specifier).ok(),
|
npm.node_resolver.url_to_node_resolution(specifier).ok(),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -682,10 +693,11 @@ fn resolve_non_graph_specifier_types(
|
||||||
referrer: &ModuleSpecifier,
|
referrer: &ModuleSpecifier,
|
||||||
state: &State,
|
state: &State,
|
||||||
) -> Result<Option<(ModuleSpecifier, MediaType)>, AnyError> {
|
) -> Result<Option<(ModuleSpecifier, MediaType)>, AnyError> {
|
||||||
let node_resolver = match state.maybe_node_resolver.as_ref() {
|
let npm = match state.maybe_npm.as_ref() {
|
||||||
Some(node_resolver) => node_resolver,
|
Some(npm) => npm,
|
||||||
None => return Ok(None), // we only support non-graph types for npm packages
|
None => return Ok(None), // we only support non-graph types for npm packages
|
||||||
};
|
};
|
||||||
|
let node_resolver = &npm.node_resolver;
|
||||||
if node_resolver.in_npm_package(referrer) {
|
if node_resolver.in_npm_package(referrer) {
|
||||||
// we're in an npm package, so use node resolution
|
// we're in an npm package, so use node resolution
|
||||||
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
Ok(Some(NodeResolution::into_specifier_and_media_type(
|
||||||
|
@ -699,13 +711,17 @@ fn resolve_non_graph_specifier_types(
|
||||||
.ok()
|
.ok()
|
||||||
.flatten(),
|
.flatten(),
|
||||||
)))
|
)))
|
||||||
} else if let Ok(npm_ref) = NpmPackageReqReference::from_str(specifier) {
|
} else if let Ok(npm_req_ref) = NpmPackageReqReference::from_str(specifier) {
|
||||||
// todo(dsherret): add support for injecting this in the graph so
|
// todo(dsherret): add support for injecting this in the graph so
|
||||||
// we don't need this special code here.
|
// we don't need this special code here.
|
||||||
// This could occur when resolving npm:@types/node when it is
|
// This could occur when resolving npm:@types/node when it is
|
||||||
// injected and not part of the graph
|
// injected and not part of the graph
|
||||||
let maybe_resolution = node_resolver.resolve_npm_req_reference(
|
let package_folder = npm
|
||||||
&npm_ref,
|
.npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module_req(npm_req_ref.req())?;
|
||||||
|
let maybe_resolution = node_resolver.resolve_npm_reference(
|
||||||
|
&package_folder,
|
||||||
|
npm_req_ref.sub_path(),
|
||||||
NodeResolutionMode::Types,
|
NodeResolutionMode::Types,
|
||||||
&PermissionsContainer::allow_all(),
|
&PermissionsContainer::allow_all(),
|
||||||
)?;
|
)?;
|
||||||
|
@ -722,9 +738,9 @@ fn op_is_node_file(state: &mut OpState, #[string] path: &str) -> bool {
|
||||||
let state = state.borrow::<State>();
|
let state = state.borrow::<State>();
|
||||||
match ModuleSpecifier::parse(path) {
|
match ModuleSpecifier::parse(path) {
|
||||||
Ok(specifier) => state
|
Ok(specifier) => state
|
||||||
.maybe_node_resolver
|
.maybe_npm
|
||||||
.as_ref()
|
.as_ref()
|
||||||
.map(|r| r.in_npm_package(&specifier))
|
.map(|n| n.node_resolver.in_npm_package(&specifier))
|
||||||
.unwrap_or(false),
|
.unwrap_or(false),
|
||||||
Err(_) => false,
|
Err(_) => false,
|
||||||
}
|
}
|
||||||
|
@ -783,7 +799,7 @@ pub fn exec(request: Request) -> Result<Response, AnyError> {
|
||||||
state.put(State::new(
|
state.put(State::new(
|
||||||
options.request.graph,
|
options.request.graph,
|
||||||
options.request.hash_data,
|
options.request.hash_data,
|
||||||
options.request.maybe_node_resolver,
|
options.request.maybe_npm,
|
||||||
options.request.maybe_tsbuildinfo,
|
options.request.maybe_tsbuildinfo,
|
||||||
options.root_map,
|
options.root_map,
|
||||||
options.remapped_specifiers,
|
options.remapped_specifiers,
|
||||||
|
@ -952,7 +968,7 @@ mod tests {
|
||||||
debug: false,
|
debug: false,
|
||||||
graph: Arc::new(graph),
|
graph: Arc::new(graph),
|
||||||
hash_data,
|
hash_data,
|
||||||
maybe_node_resolver: None,
|
maybe_npm: None,
|
||||||
maybe_tsbuildinfo: None,
|
maybe_tsbuildinfo: None,
|
||||||
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
|
root_names: vec![(specifier.clone(), MediaType::TypeScript)],
|
||||||
check_mode: TypeCheckMode::All,
|
check_mode: TypeCheckMode::All,
|
||||||
|
|
|
@ -39,6 +39,7 @@ use deno_runtime::worker::MainWorker;
|
||||||
use deno_runtime::worker::WorkerOptions;
|
use deno_runtime::worker::WorkerOptions;
|
||||||
use deno_runtime::BootstrapOptions;
|
use deno_runtime::BootstrapOptions;
|
||||||
use deno_runtime::WorkerLogLevel;
|
use deno_runtime::WorkerLogLevel;
|
||||||
|
use deno_semver::npm::NpmPackageNvReference;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use deno_semver::package::PackageReqReference;
|
use deno_semver::package::PackageReqReference;
|
||||||
|
|
||||||
|
@ -386,6 +387,9 @@ impl CliMainWorkerFactory {
|
||||||
.npm_resolver
|
.npm_resolver
|
||||||
.add_package_reqs(&[package_ref.req().clone()])
|
.add_package_reqs(&[package_ref.req().clone()])
|
||||||
.await?;
|
.await?;
|
||||||
|
let package_ref = shared
|
||||||
|
.npm_resolver
|
||||||
|
.resolve_pkg_nv_ref_from_pkg_req_ref(&package_ref)?;
|
||||||
let node_resolution =
|
let node_resolution =
|
||||||
self.resolve_binary_entrypoint(&package_ref, &permissions)?;
|
self.resolve_binary_entrypoint(&package_ref, &permissions)?;
|
||||||
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
let is_main_cjs = matches!(node_resolution, NodeResolution::CommonJs(_));
|
||||||
|
@ -511,10 +515,18 @@ impl CliMainWorkerFactory {
|
||||||
|
|
||||||
fn resolve_binary_entrypoint(
|
fn resolve_binary_entrypoint(
|
||||||
&self,
|
&self,
|
||||||
package_ref: &NpmPackageReqReference,
|
package_ref: &NpmPackageNvReference,
|
||||||
permissions: &PermissionsContainer,
|
permissions: &PermissionsContainer,
|
||||||
) -> Result<NodeResolution, AnyError> {
|
) -> Result<NodeResolution, AnyError> {
|
||||||
match self.shared.node_resolver.resolve_binary_export(package_ref) {
|
let package_folder = self
|
||||||
|
.shared
|
||||||
|
.npm_resolver
|
||||||
|
.resolve_pkg_folder_from_deno_module(package_ref.nv())?;
|
||||||
|
match self
|
||||||
|
.shared
|
||||||
|
.node_resolver
|
||||||
|
.resolve_binary_export(&package_folder, package_ref.sub_path())
|
||||||
|
{
|
||||||
Ok(node_resolution) => Ok(node_resolution),
|
Ok(node_resolution) => Ok(node_resolution),
|
||||||
Err(original_err) => {
|
Err(original_err) => {
|
||||||
// if the binary entrypoint was not found, fallback to regular node resolution
|
// if the binary entrypoint was not found, fallback to regular node resolution
|
||||||
|
@ -534,7 +546,7 @@ impl CliMainWorkerFactory {
|
||||||
/// resolve the binary entrypoint using regular node resolution
|
/// resolve the binary entrypoint using regular node resolution
|
||||||
fn resolve_binary_entrypoint_fallback(
|
fn resolve_binary_entrypoint_fallback(
|
||||||
&self,
|
&self,
|
||||||
package_ref: &NpmPackageReqReference,
|
package_ref: &NpmPackageNvReference,
|
||||||
permissions: &PermissionsContainer,
|
permissions: &PermissionsContainer,
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
) -> Result<Option<NodeResolution>, AnyError> {
|
||||||
// only fallback if the user specified a sub path
|
// only fallback if the user specified a sub path
|
||||||
|
@ -545,12 +557,16 @@ impl CliMainWorkerFactory {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
}
|
}
|
||||||
|
|
||||||
let Some(resolution) =
|
let package_folder = self
|
||||||
self.shared.node_resolver.resolve_npm_req_reference(
|
.shared
|
||||||
package_ref,
|
.npm_resolver
|
||||||
NodeResolutionMode::Execution,
|
.resolve_pkg_folder_from_deno_module(package_ref.nv())?;
|
||||||
permissions,
|
let Some(resolution) = self.shared.node_resolver.resolve_npm_reference(
|
||||||
)?
|
&package_folder,
|
||||||
|
package_ref.sub_path(),
|
||||||
|
NodeResolutionMode::Execution,
|
||||||
|
permissions,
|
||||||
|
)?
|
||||||
else {
|
else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|
|
@ -25,8 +25,6 @@ deno_fetch.workspace = true
|
||||||
deno_fs.workspace = true
|
deno_fs.workspace = true
|
||||||
deno_media_type.workspace = true
|
deno_media_type.workspace = true
|
||||||
deno_net.workspace = true
|
deno_net.workspace = true
|
||||||
deno_npm.workspace = true
|
|
||||||
deno_semver.workspace = true
|
|
||||||
digest = { version = "0.10.5", features = ["core-api", "std"] }
|
digest = { version = "0.10.5", features = ["core-api", "std"] }
|
||||||
dsa = "0.6.1"
|
dsa = "0.6.1"
|
||||||
ecb.workspace = true
|
ecb.workspace = true
|
||||||
|
|
|
@ -16,10 +16,6 @@ use deno_core::JsRuntime;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_fs::sync::MaybeSend;
|
use deno_fs::sync::MaybeSend;
|
||||||
use deno_fs::sync::MaybeSync;
|
use deno_fs::sync::MaybeSync;
|
||||||
use deno_npm::resolution::PackageReqNotFoundError;
|
|
||||||
use deno_npm::NpmPackageId;
|
|
||||||
use deno_semver::package::PackageNv;
|
|
||||||
use deno_semver::package::PackageReq;
|
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
|
|
||||||
pub mod analyze;
|
pub mod analyze;
|
||||||
|
@ -90,17 +86,6 @@ pub trait NpmResolver: std::fmt::Debug + MaybeSend + MaybeSync {
|
||||||
specifier: &ModuleSpecifier,
|
specifier: &ModuleSpecifier,
|
||||||
) -> Result<Option<PathBuf>, AnyError>;
|
) -> Result<Option<PathBuf>, AnyError>;
|
||||||
|
|
||||||
/// Resolves an npm package folder path from a Deno module.
|
|
||||||
fn resolve_package_folder_from_deno_module(
|
|
||||||
&self,
|
|
||||||
pkg_nv: &PackageNv,
|
|
||||||
) -> Result<PathBuf, AnyError>;
|
|
||||||
|
|
||||||
fn resolve_pkg_id_from_pkg_req(
|
|
||||||
&self,
|
|
||||||
req: &PackageReq,
|
|
||||||
) -> Result<NpmPackageId, PackageReqNotFoundError>;
|
|
||||||
|
|
||||||
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool;
|
fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool;
|
||||||
|
|
||||||
fn in_npm_package_at_path(&self, path: &Path) -> bool {
|
fn in_npm_package_at_path(&self, path: &Path) -> bool {
|
||||||
|
|
|
@ -106,7 +106,13 @@ impl PackageJson {
|
||||||
) -> Result<PackageJson, AnyError> {
|
) -> Result<PackageJson, AnyError> {
|
||||||
let package_json: Value = serde_json::from_str(&source)
|
let package_json: Value = serde_json::from_str(&source)
|
||||||
.map_err(|err| anyhow::anyhow!("malformed package.json {}", err))?;
|
.map_err(|err| anyhow::anyhow!("malformed package.json {}", err))?;
|
||||||
|
Self::load_from_value(path, package_json)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load_from_value(
|
||||||
|
path: PathBuf,
|
||||||
|
package_json: serde_json::Value,
|
||||||
|
) -> Result<PackageJson, AnyError> {
|
||||||
let imports_val = package_json.get("imports");
|
let imports_val = package_json.get("imports");
|
||||||
let main_val = package_json.get("main");
|
let main_val = package_json.get("main");
|
||||||
let module_val = package_json.get("module");
|
let module_val = package_json.get("module");
|
||||||
|
|
|
@ -15,10 +15,6 @@ use deno_core::url::Url;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_fs::FileSystemRc;
|
use deno_fs::FileSystemRc;
|
||||||
use deno_media_type::MediaType;
|
use deno_media_type::MediaType;
|
||||||
use deno_semver::npm::NpmPackageNvReference;
|
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
|
||||||
use deno_semver::package::PackageNv;
|
|
||||||
use deno_semver::package::PackageNvReference;
|
|
||||||
|
|
||||||
use crate::errors;
|
use crate::errors;
|
||||||
use crate::AllowAllNodePermissions;
|
use crate::AllowAllNodePermissions;
|
||||||
|
@ -329,46 +325,30 @@ impl NodeResolver {
|
||||||
Ok(resolved)
|
Ok(resolved)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn resolve_npm_req_reference(
|
|
||||||
&self,
|
|
||||||
reference: &NpmPackageReqReference,
|
|
||||||
mode: NodeResolutionMode,
|
|
||||||
permissions: &dyn NodePermissions,
|
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
|
||||||
let pkg_id = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_pkg_id_from_pkg_req(reference.req())?;
|
|
||||||
let reference = NpmPackageNvReference::new(PackageNvReference {
|
|
||||||
nv: pkg_id.nv,
|
|
||||||
sub_path: reference.sub_path().map(ToOwned::to_owned),
|
|
||||||
});
|
|
||||||
self.resolve_npm_reference(&reference, mode, permissions)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_npm_reference(
|
pub fn resolve_npm_reference(
|
||||||
&self,
|
&self,
|
||||||
reference: &NpmPackageNvReference,
|
package_folder: &Path,
|
||||||
|
sub_path: Option<&str>,
|
||||||
mode: NodeResolutionMode,
|
mode: NodeResolutionMode,
|
||||||
permissions: &dyn NodePermissions,
|
permissions: &dyn NodePermissions,
|
||||||
) -> Result<Option<NodeResolution>, AnyError> {
|
) -> Result<Option<NodeResolution>, AnyError> {
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_package_folder_from_deno_module(reference.nv())?;
|
|
||||||
let node_module_kind = NodeModuleKind::Esm;
|
let node_module_kind = NodeModuleKind::Esm;
|
||||||
let maybe_resolved_path = self
|
let maybe_resolved_path = self
|
||||||
.package_config_resolve(
|
.package_config_resolve(
|
||||||
&reference
|
&sub_path
|
||||||
.sub_path()
|
|
||||||
.map(|s| format!("./{s}"))
|
.map(|s| format!("./{s}"))
|
||||||
.unwrap_or_else(|| ".".to_string()),
|
.unwrap_or_else(|| ".".to_string()),
|
||||||
&package_folder,
|
package_folder,
|
||||||
node_module_kind,
|
node_module_kind,
|
||||||
DEFAULT_CONDITIONS,
|
DEFAULT_CONDITIONS,
|
||||||
mode,
|
mode,
|
||||||
permissions,
|
permissions,
|
||||||
)
|
)
|
||||||
.with_context(|| {
|
.with_context(|| {
|
||||||
format!("Failed resolving package config for '{reference}'")
|
format!(
|
||||||
|
"Failed resolving package config for '{}'",
|
||||||
|
package_folder.join("package.json").display()
|
||||||
|
)
|
||||||
})?;
|
})?;
|
||||||
let resolved_path = match maybe_resolved_path {
|
let resolved_path = match maybe_resolved_path {
|
||||||
Some(resolved_path) => resolved_path,
|
Some(resolved_path) => resolved_path,
|
||||||
|
@ -392,17 +372,19 @@ impl NodeResolver {
|
||||||
|
|
||||||
pub fn resolve_binary_commands(
|
pub fn resolve_binary_commands(
|
||||||
&self,
|
&self,
|
||||||
pkg_nv: &PackageNv,
|
package_folder: &Path,
|
||||||
) -> Result<Vec<String>, AnyError> {
|
) -> Result<Vec<String>, AnyError> {
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_package_folder_from_deno_module(pkg_nv)?;
|
|
||||||
let package_json_path = package_folder.join("package.json");
|
let package_json_path = package_folder.join("package.json");
|
||||||
let package_json =
|
let package_json = self
|
||||||
self.load_package_json(&AllowAllNodePermissions, package_json_path)?;
|
.load_package_json(&AllowAllNodePermissions, package_json_path.clone())?;
|
||||||
|
|
||||||
Ok(match package_json.bin {
|
Ok(match package_json.bin {
|
||||||
Some(Value::String(_)) => vec![pkg_nv.name.to_string()],
|
Some(Value::String(_)) => {
|
||||||
|
let Some(name) = &package_json.name else {
|
||||||
|
bail!("'{}' did not have a name", package_json_path.display());
|
||||||
|
};
|
||||||
|
vec![name.to_string()]
|
||||||
|
}
|
||||||
Some(Value::Object(o)) => {
|
Some(Value::Object(o)) => {
|
||||||
o.into_iter().map(|(key, _)| key).collect::<Vec<_>>()
|
o.into_iter().map(|(key, _)| key).collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
@ -412,27 +394,13 @@ impl NodeResolver {
|
||||||
|
|
||||||
pub fn resolve_binary_export(
|
pub fn resolve_binary_export(
|
||||||
&self,
|
&self,
|
||||||
pkg_ref: &NpmPackageReqReference,
|
package_folder: &Path,
|
||||||
|
sub_path: Option<&str>,
|
||||||
) -> Result<NodeResolution, AnyError> {
|
) -> Result<NodeResolution, AnyError> {
|
||||||
let pkg_nv = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_pkg_id_from_pkg_req(pkg_ref.req())?
|
|
||||||
.nv;
|
|
||||||
let bin_name = pkg_ref.sub_path();
|
|
||||||
let package_folder = self
|
|
||||||
.npm_resolver
|
|
||||||
.resolve_package_folder_from_deno_module(&pkg_nv)?;
|
|
||||||
let package_json_path = package_folder.join("package.json");
|
let package_json_path = package_folder.join("package.json");
|
||||||
let package_json =
|
let package_json = self
|
||||||
self.load_package_json(&AllowAllNodePermissions, package_json_path)?;
|
.load_package_json(&AllowAllNodePermissions, package_json_path.clone())?;
|
||||||
let bin = match &package_json.bin {
|
let bin_entry = resolve_bin_entry_value(&package_json, sub_path)?;
|
||||||
Some(bin) => bin,
|
|
||||||
None => bail!(
|
|
||||||
"package '{}' did not have a bin property in its package.json",
|
|
||||||
&pkg_nv.name,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let bin_entry = resolve_bin_entry_value(&pkg_nv, bin_name, bin)?;
|
|
||||||
let url =
|
let url =
|
||||||
ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap();
|
ModuleSpecifier::from_file_path(package_folder.join(bin_entry)).unwrap();
|
||||||
|
|
||||||
|
@ -1293,13 +1261,19 @@ impl NodeResolver {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_bin_entry_value<'a>(
|
fn resolve_bin_entry_value<'a>(
|
||||||
pkg_nv: &PackageNv,
|
package_json: &'a PackageJson,
|
||||||
bin_name: Option<&str>,
|
bin_name: Option<&str>,
|
||||||
bin: &'a Value,
|
|
||||||
) -> Result<&'a str, AnyError> {
|
) -> Result<&'a str, AnyError> {
|
||||||
|
let bin = match &package_json.bin {
|
||||||
|
Some(bin) => bin,
|
||||||
|
None => bail!(
|
||||||
|
"'{}' did not have a bin property",
|
||||||
|
package_json.path.display(),
|
||||||
|
),
|
||||||
|
};
|
||||||
let bin_entry = match bin {
|
let bin_entry = match bin {
|
||||||
Value::String(_) => {
|
Value::String(_) => {
|
||||||
if bin_name.is_some() && bin_name.unwrap() != pkg_nv.name {
|
if bin_name.is_some() && bin_name != package_json.name.as_deref() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(bin)
|
Some(bin)
|
||||||
|
@ -1308,29 +1282,50 @@ fn resolve_bin_entry_value<'a>(
|
||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
if let Some(bin_name) = bin_name {
|
if let Some(bin_name) = bin_name {
|
||||||
o.get(bin_name)
|
o.get(bin_name)
|
||||||
} else if o.len() == 1 || o.len() > 1 && o.values().all(|v| v == o.values().next().unwrap()) {
|
} else if o.len() == 1
|
||||||
|
|| o.len() > 1 && o.values().all(|v| v == o.values().next().unwrap())
|
||||||
|
{
|
||||||
o.values().next()
|
o.values().next()
|
||||||
} else {
|
} else {
|
||||||
o.get(&pkg_nv.name)
|
package_json.name.as_ref().and_then(|n| o.get(n))
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
_ => bail!("package '{}' did not have a bin property with a string or object value in its package.json", pkg_nv),
|
_ => bail!(
|
||||||
|
"'{}' did not have a bin property with a string or object value",
|
||||||
|
package_json.path.display()
|
||||||
|
),
|
||||||
};
|
};
|
||||||
let bin_entry = match bin_entry {
|
let bin_entry = match bin_entry {
|
||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {
|
None => {
|
||||||
|
let prefix = package_json
|
||||||
|
.name
|
||||||
|
.as_ref()
|
||||||
|
.map(|n| {
|
||||||
|
let mut prefix = format!("npm:{}", n);
|
||||||
|
if let Some(version) = &package_json.version {
|
||||||
|
prefix.push('@');
|
||||||
|
prefix.push_str(version);
|
||||||
|
}
|
||||||
|
prefix.push('/');
|
||||||
|
prefix
|
||||||
|
})
|
||||||
|
.unwrap_or_default();
|
||||||
let keys = bin
|
let keys = bin
|
||||||
.as_object()
|
.as_object()
|
||||||
.map(|o| {
|
.map(|o| {
|
||||||
o.keys()
|
o.keys()
|
||||||
.map(|k| format!(" * npm:{pkg_nv}/{k}"))
|
.map(|k| format!(" * {prefix}{k}"))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
bail!(
|
bail!(
|
||||||
"package '{}' did not have a bin entry for '{}' in its package.json{}",
|
"'{}' did not have a bin entry{}{}",
|
||||||
pkg_nv,
|
package_json.path.display(),
|
||||||
bin_name.unwrap_or(&pkg_nv.name),
|
bin_name
|
||||||
|
.or(package_json.name.as_deref())
|
||||||
|
.map(|name| format!(" for '{}'", name))
|
||||||
|
.unwrap_or_default(),
|
||||||
if keys.is_empty() {
|
if keys.is_empty() {
|
||||||
"".to_string()
|
"".to_string()
|
||||||
} else {
|
} else {
|
||||||
|
@ -1342,8 +1337,8 @@ fn resolve_bin_entry_value<'a>(
|
||||||
match bin_entry {
|
match bin_entry {
|
||||||
Value::String(s) => Ok(s),
|
Value::String(s) => Ok(s),
|
||||||
_ => bail!(
|
_ => bail!(
|
||||||
"package '{}' had a non-string sub property of bin in its package.json",
|
"'{}' had a non-string sub property of bin",
|
||||||
pkg_nv,
|
package_json.path.display(),
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1595,102 +1590,141 @@ mod tests {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
fn build_package_json(json: Value) -> PackageJson {
|
||||||
|
PackageJson::load_from_value(PathBuf::from("/package.json"), json).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_resolve_bin_entry_value() {
|
fn test_resolve_bin_entry_value() {
|
||||||
// should resolve the specified value
|
// should resolve the specified value
|
||||||
let value = json!({
|
let pkg_json = build_package_json(json!({
|
||||||
"bin1": "./value1",
|
"name": "pkg",
|
||||||
"bin2": "./value2",
|
"version": "1.1.1",
|
||||||
"test": "./value3",
|
"bin": {
|
||||||
});
|
"bin1": "./value1",
|
||||||
|
"bin2": "./value2",
|
||||||
|
"pkg": "./value3",
|
||||||
|
}
|
||||||
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_bin_entry_value(
|
resolve_bin_entry_value(&pkg_json, Some("bin1")).unwrap(),
|
||||||
&PackageNv::from_str("test@1.1.1").unwrap(),
|
|
||||||
Some("bin1"),
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"./value1"
|
"./value1"
|
||||||
);
|
);
|
||||||
|
|
||||||
// should resolve the value with the same name when not specified
|
// should resolve the value with the same name when not specified
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_bin_entry_value(
|
resolve_bin_entry_value(&pkg_json, None).unwrap(),
|
||||||
&PackageNv::from_str("test@1.1.1").unwrap(),
|
|
||||||
None,
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"./value3"
|
"./value3"
|
||||||
);
|
);
|
||||||
|
|
||||||
// should not resolve when specified value does not exist
|
// should not resolve when specified value does not exist
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_bin_entry_value(
|
resolve_bin_entry_value(&pkg_json, Some("other"),)
|
||||||
&PackageNv::from_str("test@1.1.1").unwrap(),
|
.err()
|
||||||
Some("other"),
|
.unwrap()
|
||||||
&value
|
.to_string(),
|
||||||
)
|
|
||||||
.err()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
concat!(
|
concat!(
|
||||||
"package 'test@1.1.1' did not have a bin entry for 'other' in its package.json\n",
|
"'/package.json' did not have a bin entry for 'other'\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Possibilities:\n",
|
"Possibilities:\n",
|
||||||
" * npm:test@1.1.1/bin1\n",
|
" * npm:pkg@1.1.1/bin1\n",
|
||||||
" * npm:test@1.1.1/bin2\n",
|
" * npm:pkg@1.1.1/bin2\n",
|
||||||
" * npm:test@1.1.1/test"
|
" * npm:pkg@1.1.1/pkg"
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// should not resolve when default value can't be determined
|
// should not resolve when default value can't be determined
|
||||||
|
let pkg_json = build_package_json(json!({
|
||||||
|
"name": "pkg",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"bin": {
|
||||||
|
"bin": "./value1",
|
||||||
|
"bin2": "./value2",
|
||||||
|
}
|
||||||
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_bin_entry_value(
|
resolve_bin_entry_value(&pkg_json, None)
|
||||||
&PackageNv::from_str("asdf@1.2.3").unwrap(),
|
.err()
|
||||||
None,
|
.unwrap()
|
||||||
&value
|
.to_string(),
|
||||||
)
|
|
||||||
.err()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
concat!(
|
concat!(
|
||||||
"package 'asdf@1.2.3' did not have a bin entry for 'asdf' in its package.json\n",
|
"'/package.json' did not have a bin entry for 'pkg'\n",
|
||||||
"\n",
|
"\n",
|
||||||
"Possibilities:\n",
|
"Possibilities:\n",
|
||||||
" * npm:asdf@1.2.3/bin1\n",
|
" * npm:pkg@1.1.1/bin\n",
|
||||||
" * npm:asdf@1.2.3/bin2\n",
|
" * npm:pkg@1.1.1/bin2",
|
||||||
" * npm:asdf@1.2.3/test"
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
// should resolve since all the values are the same
|
// should resolve since all the values are the same
|
||||||
let value = json!({
|
let pkg_json = build_package_json(json!({
|
||||||
"bin1": "./value",
|
"name": "pkg",
|
||||||
"bin2": "./value",
|
"version": "1.2.3",
|
||||||
});
|
"bin": {
|
||||||
|
"bin1": "./value",
|
||||||
|
"bin2": "./value",
|
||||||
|
}
|
||||||
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_bin_entry_value(
|
resolve_bin_entry_value(&pkg_json, None,).unwrap(),
|
||||||
&PackageNv::from_str("test@1.2.3").unwrap(),
|
|
||||||
None,
|
|
||||||
&value
|
|
||||||
)
|
|
||||||
.unwrap(),
|
|
||||||
"./value"
|
"./value"
|
||||||
);
|
);
|
||||||
|
|
||||||
// should not resolve when specified and is a string
|
// should not resolve when specified and is a string
|
||||||
let value = json!("./value");
|
let pkg_json = build_package_json(json!({
|
||||||
|
"name": "pkg",
|
||||||
|
"version": "1.2.3",
|
||||||
|
"bin": "./value",
|
||||||
|
}));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
resolve_bin_entry_value(
|
resolve_bin_entry_value(&pkg_json, Some("path"),)
|
||||||
&PackageNv::from_str("test@1.2.3").unwrap(),
|
.err()
|
||||||
Some("path"),
|
.unwrap()
|
||||||
&value
|
.to_string(),
|
||||||
|
"'/package.json' did not have a bin entry for 'path'"
|
||||||
|
);
|
||||||
|
|
||||||
|
// no version in the package.json
|
||||||
|
let pkg_json = build_package_json(json!({
|
||||||
|
"name": "pkg",
|
||||||
|
"bin": {
|
||||||
|
"bin1": "./value1",
|
||||||
|
"bin2": "./value2",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
assert_eq!(
|
||||||
|
resolve_bin_entry_value(&pkg_json, None)
|
||||||
|
.err()
|
||||||
|
.unwrap()
|
||||||
|
.to_string(),
|
||||||
|
concat!(
|
||||||
|
"'/package.json' did not have a bin entry for 'pkg'\n",
|
||||||
|
"\n",
|
||||||
|
"Possibilities:\n",
|
||||||
|
" * npm:pkg/bin1\n",
|
||||||
|
" * npm:pkg/bin2",
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// no name or version in the package.json
|
||||||
|
let pkg_json = build_package_json(json!({
|
||||||
|
"bin": {
|
||||||
|
"bin1": "./value1",
|
||||||
|
"bin2": "./value2",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
assert_eq!(
|
||||||
|
resolve_bin_entry_value(&pkg_json, None)
|
||||||
|
.err()
|
||||||
|
.unwrap()
|
||||||
|
.to_string(),
|
||||||
|
concat!(
|
||||||
|
"'/package.json' did not have a bin entry\n",
|
||||||
|
"\n",
|
||||||
|
"Possibilities:\n",
|
||||||
|
" * bin1\n",
|
||||||
|
" * bin2",
|
||||||
)
|
)
|
||||||
.err()
|
|
||||||
.unwrap()
|
|
||||||
.to_string(),
|
|
||||||
"package 'test@1.2.3' did not have a bin entry for 'path' in its package.json"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue