From be97170a193e8cecc5ce03ecd3c1d0add4a06bf7 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 25 Oct 2023 14:39:00 -0400 Subject: feat(unstable): ability to `npm install` then `deno run main.ts` (#20967) This PR adds a new unstable "bring your own node_modules" (BYONM) functionality currently behind a `--unstable-byonm` flag (`"unstable": ["byonm"]` in a deno.json). This enables users to run a separate install command (ex. `npm install`, `pnpm install`) then run `deno run main.ts` and Deno will respect the layout of the node_modules directory as setup by the separate install command. It also works with npm/yarn/pnpm workspaces. For this PR, the behaviour is opted into by specifying `--unstable-byonm`/`"unstable": ["byonm"]`, but in the future we may make this the default behaviour as outlined in https://github.com/denoland/deno/issues/18967#issuecomment-1761248941 This is an extremely rough initial implementation. Errors are terrible in this and the LSP requires frequent restarts. Improvements will be done in follow up PRs. --- cli/cache/mod.rs | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) (limited to 'cli/cache') diff --git a/cli/cache/mod.rs b/cli/cache/mod.rs index 1d6a79963..5cc91f50f 100644 --- a/cli/cache/mod.rs +++ b/cli/cache/mod.rs @@ -4,6 +4,7 @@ use crate::args::CacheSetting; use crate::errors::get_error_class_name; use crate::file_fetcher::FetchOptions; use crate::file_fetcher::FileFetcher; +use crate::npm::CliNpmResolver; use crate::util::fs::atomic_write_file; use deno_ast::MediaType; @@ -101,10 +102,10 @@ pub struct FetchCacher { file_fetcher: Arc, file_header_overrides: HashMap>, global_http_cache: Arc, + npm_resolver: Arc, parsed_source_cache: Arc, permissions: PermissionsContainer, cache_info_enabled: bool, - maybe_local_node_modules_url: Option, } impl FetchCacher { @@ -113,19 +114,19 @@ impl FetchCacher { file_fetcher: Arc, file_header_overrides: HashMap>, global_http_cache: Arc, + npm_resolver: Arc, parsed_source_cache: Arc, permissions: PermissionsContainer, - maybe_local_node_modules_url: Option, ) -> Self { Self { emit_cache, file_fetcher, file_header_overrides, global_http_cache, + npm_resolver, parsed_source_cache, permissions, cache_info_enabled: false, - maybe_local_node_modules_url, } } @@ -214,20 +215,18 @@ impl Loader for FetchCacher { ) -> LoadFuture { use deno_graph::source::CacheSetting as LoaderCacheSetting; - if let Some(node_modules_url) = self.maybe_local_node_modules_url.as_ref() { + if specifier.path().contains("/node_modules/") { // The specifier might be in a completely different symlinked tree than - // what the resolved node_modules_url is in (ex. `/my-project-1/node_modules` - // symlinked to `/my-project-2/node_modules`), so first check if the path - // is in a node_modules dir to avoid needlessly canonicalizing, then compare + // what the node_modules url is in (ex. `/my-project-1/node_modules` + // symlinked to `/my-project-2/node_modules`), so first we checked if the path + // is in a node_modules dir to avoid needlessly canonicalizing, then now compare // against the canonicalized specifier. - if specifier.path().contains("/node_modules/") { - let specifier = - crate::node::resolve_specifier_into_node_modules(specifier); - if specifier.as_str().starts_with(node_modules_url.as_str()) { - return Box::pin(futures::future::ready(Ok(Some( - LoadResponse::External { specifier }, - )))); - } + let specifier = + crate::node::resolve_specifier_into_node_modules(specifier); + if self.npm_resolver.in_npm_package(&specifier) { + return Box::pin(futures::future::ready(Ok(Some( + LoadResponse::External { specifier }, + )))); } } -- cgit v1.2.3