summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--cli/graph_util.rs6
-rw-r--r--cli/resolver.rs14
-rw-r--r--cli/tests/integration/npm_tests.rs71
-rw-r--r--cli/tools/run.rs37
4 files changed, 116 insertions, 12 deletions
diff --git a/cli/graph_util.rs b/cli/graph_util.rs
index 53d06071c..90c4f8b38 100644
--- a/cli/graph_util.rs
+++ b/cli/graph_util.rs
@@ -296,6 +296,12 @@ impl ModuleGraphBuilder {
loader: &mut dyn deno_graph::source::Loader,
options: deno_graph::BuildOptions<'a>,
) -> Result<(), AnyError> {
+ // ensure an "npm install" is done if the user has explicitly
+ // opted into using a node_modules directory
+ if self.options.node_modules_dir_enablement() == Some(true) {
+ self.resolver.force_top_level_package_json_install().await?;
+ }
+
graph.build(roots, loader, options).await;
// ensure that the top level package.json is installed if a
diff --git a/cli/resolver.rs b/cli/resolver.rs
index 7f49116f4..6fa8eaabe 100644
--- a/cli/resolver.rs
+++ b/cli/resolver.rs
@@ -182,14 +182,20 @@ impl CliGraphResolver {
self
}
+ pub async fn force_top_level_package_json_install(
+ &self,
+ ) -> Result<(), AnyError> {
+ self
+ .package_json_deps_installer
+ .ensure_top_level_install()
+ .await
+ }
+
pub async fn top_level_package_json_install_if_necessary(
&self,
) -> Result<(), AnyError> {
if self.found_package_json_dep_flag.is_raised() {
- self
- .package_json_deps_installer
- .ensure_top_level_install()
- .await?;
+ self.force_top_level_package_json_install().await?;
}
Ok(())
}
diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs
index 73ac029df..bd19ed26f 100644
--- a/cli/tests/integration/npm_tests.rs
+++ b/cli/tests/integration/npm_tests.rs
@@ -1,6 +1,7 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
use deno_core::serde_json;
+use deno_core::serde_json::json;
use deno_core::serde_json::Value;
use pretty_assertions::assert_eq;
use std::process::Stdio;
@@ -1924,3 +1925,73 @@ pub fn node_modules_dir_config_file() {
.run();
assert!(node_modules_dir.exists());
}
+
+#[test]
+fn top_level_install_package_json_explicit_opt_in() {
+ let test_context = TestContextBuilder::for_npm().use_temp_cwd().build();
+ let temp_dir = test_context.temp_dir();
+ let node_modules_dir = temp_dir.path().join("node_modules");
+ let rm_created_files = || {
+ std::fs::remove_dir_all(&node_modules_dir).unwrap();
+ std::fs::remove_file(temp_dir.path().join("deno.lock")).unwrap();
+ };
+
+ // when the node_modules_dir is explicitly opted into, we should always
+ // ensure a top level package.json install occurs
+ temp_dir.write("deno.json", "{ \"nodeModulesDir\": true }");
+ temp_dir.write(
+ "package.json",
+ "{ \"dependencies\": { \"@denotest/esm-basic\": \"1.0\" }}",
+ );
+
+ temp_dir.write("main.ts", "console.log(5);");
+ let output = test_context.new_command().args("cache main.ts").run();
+ output.assert_matches_text(
+ concat!(
+ "Download http://localhost:4545/npm/registry/@denotest/esm-basic\n",
+ "Download http://localhost:4545/npm/registry/@denotest/esm-basic/1.0.0.tgz\n",
+ "Initialize @denotest/esm-basic@1.0.0\n",
+ )
+ );
+
+ rm_created_files();
+ let output = test_context
+ .new_command()
+ .args_vec(["eval", "console.log(5)"])
+ .run();
+ output.assert_matches_text(concat!(
+ "Initialize @denotest/esm-basic@1.0.0\n",
+ "5\n"
+ ));
+
+ rm_created_files();
+ let output = test_context
+ .new_command()
+ .args("run -")
+ .stdin("console.log(5)")
+ .run();
+ output.assert_matches_text(concat!(
+ "Initialize @denotest/esm-basic@1.0.0\n",
+ "5\n"
+ ));
+
+ // now ensure this is cached in the lsp
+ rm_created_files();
+ let mut client = test_context.new_lsp_command().build();
+ client.initialize_default();
+ let file_uri = temp_dir.uri().join("file.ts").unwrap();
+ client.did_open(json!({
+ "textDocument": {
+ "uri": file_uri,
+ "languageId": "typescript",
+ "version": 1,
+ "text": "",
+ }
+ }));
+ client.write_request(
+ "deno/cache",
+ json!({ "referrer": { "uri": file_uri }, "uris": [] }),
+ );
+
+ assert!(node_modules_dir.join("@denotest").exists());
+}
diff --git a/cli/tools/run.rs b/cli/tools/run.rs
index 99312d5b9..4805ea704 100644
--- a/cli/tools/run.rs
+++ b/cli/tools/run.rs
@@ -47,6 +47,8 @@ To grant permissions, set them before the script argument. For example:
let main_module = cli_options.resolve_main_module()?;
+ maybe_npm_install(&factory).await?;
+
let permissions = PermissionsContainer::new(Permissions::from_options(
&cli_options.permissions_options(),
)?);
@@ -63,9 +65,11 @@ pub async fn run_from_stdin(flags: Flags) -> Result<i32, AnyError> {
let factory = CliFactory::from_flags(flags).await?;
let cli_options = factory.cli_options();
let main_module = cli_options.resolve_main_module()?;
+
+ maybe_npm_install(&factory).await?;
+
let file_fetcher = factory.file_fetcher()?;
let worker_factory = factory.create_cli_main_worker_factory().await?;
-
let permissions = PermissionsContainer::new(Permissions::from_options(
&cli_options.permissions_options(),
)?);
@@ -103,9 +107,11 @@ async fn run_with_watch(flags: Flags) -> Result<i32, AnyError> {
let cli_options = factory.cli_options();
let clear_screen = !cli_options.no_clear_screen();
let main_module = cli_options.resolve_main_module()?;
+
+ maybe_npm_install(&factory).await?;
+
let create_cli_main_worker_factory =
factory.create_cli_main_worker_factory_func().await?;
-
let operation = |main_module: ModuleSpecifier| {
file_watcher.reset();
let permissions = PermissionsContainer::new(Permissions::from_options(
@@ -144,12 +150,10 @@ pub async fn eval_command(
let factory = CliFactory::from_flags(flags).await?;
let cli_options = factory.cli_options();
let file_fetcher = factory.file_fetcher()?;
- let main_worker_factory = factory.create_cli_main_worker_factory().await?;
-
let main_module = cli_options.resolve_main_module()?;
- let permissions = PermissionsContainer::new(Permissions::from_options(
- &cli_options.permissions_options(),
- )?);
+
+ maybe_npm_install(&factory).await?;
+
// Create a dummy source file.
let source_code = if eval_flags.print {
format!("console.log({})", eval_flags.code)
@@ -171,9 +175,26 @@ pub async fn eval_command(
// to allow module access by TS compiler.
file_fetcher.insert_cached(file);
- let mut worker = main_worker_factory
+ let permissions = PermissionsContainer::new(Permissions::from_options(
+ &cli_options.permissions_options(),
+ )?);
+ let worker_factory = factory.create_cli_main_worker_factory().await?;
+ let mut worker = worker_factory
.create_main_worker(main_module, permissions)
.await?;
let exit_code = worker.run().await?;
Ok(exit_code)
}
+
+async fn maybe_npm_install(factory: &CliFactory) -> Result<(), AnyError> {
+ // ensure an "npm install" is done if the user has explicitly
+ // opted into using a node_modules directory
+ if factory.cli_options().node_modules_dir_enablement() == Some(true) {
+ factory
+ .package_json_deps_installer()
+ .await?
+ .ensure_top_level_install()
+ .await?;
+ }
+ Ok(())
+}