diff --git a/cli/args/config_file.rs b/cli/args/config_file.rs index 8b52d7825e..ed31a47a64 100644 --- a/cli/args/config_file.rs +++ b/cli/args/config_file.rs @@ -668,12 +668,13 @@ pub struct ConfigFileJson { pub bench: Option, pub lock: Option, pub exclude: Option, + pub node_modules_dir: Option, } #[derive(Clone, Debug)] pub struct ConfigFile { pub specifier: ModuleSpecifier, - pub json: ConfigFileJson, + json: ConfigFileJson, } impl ConfigFile { @@ -865,6 +866,10 @@ impl ConfigFile { self.json.import_map.clone() } + pub fn node_modules_dir(&self) -> Option { + self.json.node_modules_dir + } + pub fn to_import_map_value(&self) -> Value { let mut value = serde_json::Map::with_capacity(2); if let Some(imports) = &self.json.imports { diff --git a/cli/args/flags.rs b/cli/args/flags.rs index fa28241a3a..63ec2b9471 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -2431,7 +2431,7 @@ fn local_npm_arg() -> Arg { .value_parser(value_parser!(bool)) .default_missing_value("true") .require_equals(true) - .help("Creates a local node_modules folder") + .help("Enables or disables the use of a local node_modules folder for npm packages") } fn unsafely_ignore_certificate_errors_arg() -> Arg { diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 53dad9cae0..fef27f464d 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -1184,14 +1184,17 @@ fn resolve_local_node_modules_folder( maybe_config_file: Option<&ConfigFile>, maybe_package_json: Option<&PackageJson>, ) -> Result, AnyError> { - let path = if flags.node_modules_dir == Some(false) { + let use_node_modules_dir = flags + .node_modules_dir + .or_else(|| maybe_config_file.and_then(|c| c.node_modules_dir())); + let path = if use_node_modules_dir == Some(false) { return Ok(None); } else if let Some(state) = &*NPM_PROCESS_STATE { return Ok(state.local_node_modules_path.as_ref().map(PathBuf::from)); } else if let Some(package_json_path) = maybe_package_json.map(|c| &c.path) { // always auto-discover the local_node_modules_folder when a package.json exists package_json_path.parent().unwrap().join("node_modules") - } else if flags.node_modules_dir.is_none() { + } else if use_node_modules_dir.is_none() { return Ok(None); } else if let Some(config_path) = maybe_config_file .as_ref() diff --git a/cli/schemas/config-file.v1.json b/cli/schemas/config-file.v1.json index 0006997677..8640428775 100644 --- a/cli/schemas/config-file.v1.json +++ b/cli/schemas/config-file.v1.json @@ -422,6 +422,10 @@ } } }, + "nodeModulesDir": { + "description": "Enables or disables the use of a local node_modules folder for npm packages. Alternatively, use the `--node-modules-dir` or `--node-modules-dir=false` flag.", + "type": "boolean" + }, "tasks": { "description": "Configuration for deno task", "type": "object", diff --git a/cli/tests/integration/npm_tests.rs b/cli/tests/integration/npm_tests.rs index dc3aa7b111..40214315a5 100644 --- a/cli/tests/integration/npm_tests.rs +++ b/cli/tests/integration/npm_tests.rs @@ -1880,3 +1880,34 @@ fn binary_package_with_optional_dependencies() { } } } + +#[test] +pub fn node_modules_dir_config_file() { + 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_node_modules = || std::fs::remove_dir_all(&node_modules_dir).unwrap(); + + temp_dir.write("deno.json", r#"{ "nodeModulesDir": true }"#); + temp_dir.write("main.ts", "import 'npm:@denotest/esm-basic';"); + + let deno_cache_cmd = test_context.new_command().args("cache --quiet main.ts"); + deno_cache_cmd.run(); + + assert!(node_modules_dir.exists()); + rm_node_modules(); + temp_dir.write("deno.json", r#"{ "nodeModulesDir": false }"#); + + deno_cache_cmd.run(); + assert!(!node_modules_dir.exists()); + + temp_dir.write("package.json", r#"{}"#); + deno_cache_cmd.run(); + assert!(!node_modules_dir.exists()); + + test_context + .new_command() + .args("cache --quiet --node-modules-dir main.ts") + .run(); + assert!(node_modules_dir.exists()); +}