From 1a0cb5b5312941521ab021cfe9eaed498f35900b Mon Sep 17 00:00:00 2001 From: David Sherret Date: Mon, 14 Oct 2024 20:48:39 -0400 Subject: feat(unstable): `--unstable-detect-cjs` for respecting explicit `"type": "commonjs"` (#26149) When using the `--unstable-detect-cjs` flag or adding `"unstable": ["detect-cjs"]` to a deno.json, it will make a JS file CJS if the closest package.json contains `"type": "commonjs"` and the file is not an ESM module (no TLA, no `import.meta`, no `import`/`export`). --- cli/args/mod.rs | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 07906a86a..f905e186b 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -1576,6 +1576,11 @@ impl CliOptions { || self.workspace().has_unstable("bare-node-builtins") } + pub fn unstable_detect_cjs(&self) -> bool { + self.flags.unstable_config.detect_cjs + || self.workspace().has_unstable("detect-cjs") + } + fn byonm_enabled(&self) -> bool { // check if enabled via unstable self.node_modules_dir().ok().flatten() == Some(NodeModulesDirMode::Manual) @@ -1620,21 +1625,17 @@ impl CliOptions { }); if !from_config_file.is_empty() { - // collect unstable granular flags - let mut all_valid_unstable_flags: Vec<&str> = - crate::UNSTABLE_GRANULAR_FLAGS - .iter() - .map(|granular_flag| granular_flag.name) - .collect(); - - let mut another_unstable_flags = Vec::from([ - "sloppy-imports", - "byonm", - "bare-node-builtins", - "fmt-component", - ]); - // add more unstable flags to the same vector holding granular flags - all_valid_unstable_flags.append(&mut another_unstable_flags); + let all_valid_unstable_flags: Vec<&str> = crate::UNSTABLE_GRANULAR_FLAGS + .iter() + .map(|granular_flag| granular_flag.name) + .chain([ + "sloppy-imports", + "byonm", + "bare-node-builtins", + "fmt-component", + "detect-cjs", + ]) + .collect(); // check and warn if the unstable flag of config file isn't supported, by // iterating through the vector holding the unstable flags -- cgit v1.2.3 From 69e1d7a4edb45c8b4cb15f64ee89cec8a693be5e Mon Sep 17 00:00:00 2001 From: Nathan Whitaker <17734409+nathanwhit@users.noreply.github.com> Date: Wed, 23 Oct 2024 15:01:45 -0700 Subject: fix(install): cache type only module deps in `deno install` (#26497) Fixes https://github.com/denoland/deno/issues/26180. --- cli/args/mod.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index f905e186b..d8f553101 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -963,6 +963,9 @@ impl CliOptions { match self.sub_command() { DenoSubcommand::Cache(_) => GraphKind::All, DenoSubcommand::Check(_) => GraphKind::TypesOnly, + DenoSubcommand::Install(InstallFlags { + kind: InstallKind::Local(_), + }) => GraphKind::All, _ => self.type_check_mode().as_graph_kind(), } } -- cgit v1.2.3 From 5f0bb3c6f4328003012e98ba70ce18e4e2e842de Mon Sep 17 00:00:00 2001 From: Marvin Hagemeister Date: Thu, 24 Oct 2024 20:03:56 +0200 Subject: fix: `.npmrc` settings not being passed to install/add command (#26473) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We weren't passing the resolved npmrc settings to the install commands. This lead us to always fall back to the default registry url instead of using the one from npmrc. Fixes https://github.com/denoland/deno/issues/26139 Fixes https://github.com/denoland/deno/issues/26033 Fixes https://github.com/denoland/deno/issues/25924 Fixes https://github.com/denoland/deno/issues/25822 Fixes https://github.com/denoland/deno/issues/26152 --------- Co-authored-by: Bartek Iwańczuk --- cli/args/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index d8f553101..927f43e85 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -578,6 +578,7 @@ fn discover_npmrc( let resolved = npmrc .as_resolved(npm_registry_url()) .context("Failed to resolve .npmrc options")?; + log::debug!(".npmrc found at: '{}'", path.display()); Ok(Arc::new(resolved)) } -- cgit v1.2.3 From 3b28446000d8d063c07ef320314ef493a9e0bffa Mon Sep 17 00:00:00 2001 From: HasanAlrimawi <141642411+HasanAlrimawi@users.noreply.github.com> Date: Tue, 29 Oct 2024 23:55:41 +0200 Subject: fix: support watch flag to enable watching other files than the main module on serve subcommand (#26622) Closes #26618 --- cli/args/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 927f43e85..f5ecc0449 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -1672,6 +1672,10 @@ impl CliOptions { if let DenoSubcommand::Run(RunFlags { watch: Some(WatchFlagsWithPaths { paths, .. }), .. + }) + | DenoSubcommand::Serve(ServeFlags { + watch: Some(WatchFlagsWithPaths { paths, .. }), + .. }) = &self.flags.subcommand { full_paths.extend(paths.iter().map(|path| self.initial_cwd.join(path))); -- cgit v1.2.3 From 5f5ac4063142c6c411486581f2f26cf51a32d7e3 Mon Sep 17 00:00:00 2001 From: HasanAlrimawi <141642411+HasanAlrimawi@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:32:18 +0200 Subject: fix(serve): support serve hmr (#26078) This PR addresses issue #25600 Changes: Updated `fn has_hmr` to check `serve` subcommand and return its hmr value if found, in order to run the worker in serve mode with hmr_runner. Thus the hmr event can be dispatched upon changes on the file served. --- cli/args/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index f5ecc0449..754cd38fa 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -1452,6 +1452,12 @@ impl CliOptions { watch: Some(WatchFlagsWithPaths { hmr, .. }), .. }) = &self.flags.subcommand + { + *hmr + } else if let DenoSubcommand::Serve(ServeFlags { + watch: Some(WatchFlagsWithPaths { hmr, .. }), + .. + }) = &self.flags.subcommand { *hmr } else { -- cgit v1.2.3 From 90edca21a26fd2decd0603fea37af10d1e11e454 Mon Sep 17 00:00:00 2001 From: David Sherret Date: Thu, 31 Oct 2024 11:35:17 -0400 Subject: fix: surface package.json location on dep parse failure (#26665) Related: https://github.com/denoland/deno/issues/26653 --- cli/args/mod.rs | 1 + 1 file changed, 1 insertion(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 754cd38fa..d72526462 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -46,6 +46,7 @@ pub use flags::*; pub use lockfile::CliLockfile; pub use lockfile::CliLockfileReadFromPathOptions; pub use package_json::NpmInstallDepsProvider; +pub use package_json::PackageJsonDepValueParseWithLocationError; use deno_ast::ModuleSpecifier; use deno_core::anyhow::bail; -- cgit v1.2.3 From 826e42a5b5880c974ae019a7a21aade6a718062c Mon Sep 17 00:00:00 2001 From: David Sherret Date: Fri, 1 Nov 2024 12:27:00 -0400 Subject: fix: improved support for cjs and cts modules (#26558) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * cts support * better cjs/cts type checking * deno compile cjs/cts support * More efficient detect cjs (going towards stabilization) * Determination of whether .js, .ts, .jsx, or .tsx is cjs or esm is only done after loading * Support `import x = require(...);` Co-authored-by: Bartek Iwańczuk --- cli/args/mod.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index d72526462..e19025f8b 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -201,6 +201,8 @@ pub fn ts_config_to_transpile_and_emit_options( precompile_jsx_dynamic_props: None, transform_jsx, var_decl_imports: false, + // todo(dsherret): support verbatim_module_syntax here properly + verbatim_module_syntax: false, }, deno_ast::EmitOptions { inline_sources: options.inline_sources, @@ -1602,6 +1604,15 @@ impl CliOptions { } pub fn use_byonm(&self) -> bool { + if matches!( + self.sub_command(), + DenoSubcommand::Install(_) + | DenoSubcommand::Add(_) + | DenoSubcommand::Remove(_) + ) { + // For `deno install/add/remove` we want to force the managed resolver so it can set up `node_modules/` directory. + return false; + } if self.node_modules_dir().ok().flatten().is_none() && self.maybe_node_modules_folder.is_some() && self -- cgit v1.2.3 From aa546189be730163ee5370029e4dfdb3b454ab96 Mon Sep 17 00:00:00 2001 From: snek Date: Wed, 13 Nov 2024 11:38:46 +0100 Subject: feat: OpenTelemetry Tracing API and Exporting (#26710) Initial import of OTEL code supporting tracing. Metrics soon to come. Implements APIs for https://jsr.io/@deno/otel so that code using OpenTelemetry.js just works tm. There is still a lot of work to do with configuration and adding built-in tracing to core APIs, which will come in followup PRs. --------- Co-authored-by: Luca Casonato --- cli/args/mod.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index e19025f8b..3aaf2bd43 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -27,6 +27,7 @@ use deno_npm::npm_rc::ResolvedNpmRc; use deno_npm::resolution::ValidSerializedNpmResolutionSnapshot; use deno_npm::NpmSystemInfo; use deno_path_util::normalize_path; +use deno_runtime::ops::otel::OtelConfig; use deno_semver::npm::NpmPackageReqReference; use import_map::resolve_import_map_value_from_specifier; @@ -1129,6 +1130,23 @@ impl CliOptions { } } + pub fn otel_config(&self) -> Option { + if self + .flags + .unstable_config + .features + .contains(&String::from("otel")) + { + Some(OtelConfig { + runtime_name: Cow::Borrowed("deno"), + runtime_version: Cow::Borrowed(crate::version::DENO_VERSION_INFO.deno), + ..Default::default() + }) + } else { + None + } + } + pub fn env_file_name(&self) -> Option<&String> { self.flags.env_file.as_ref() } -- cgit v1.2.3 From f091d1ad69b4e5217ae3272b641171781a372c4f Mon Sep 17 00:00:00 2001 From: David Sherret Date: Wed, 13 Nov 2024 10:10:09 -0500 Subject: feat(node): stabilize detecting if CJS via `"type": "commonjs"` in a package.json (#26439) This will respect `"type": "commonjs"` in a package.json to determine if `.js`/`.jsx`/`.ts`/.tsx` files are CJS or ESM. If the file is found to be ESM it will be loaded as ESM though. --- cli/args/mod.rs | 70 +++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 56 insertions(+), 14 deletions(-) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 3aaf2bd43..5e5bae87d 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -7,6 +7,7 @@ mod import_map; mod lockfile; mod package_json; +use deno_ast::MediaType; use deno_ast::SourceMapOption; use deno_config::deno_json::NodeModulesDirMode; use deno_config::workspace::CreateResolverOptions; @@ -34,7 +35,6 @@ use import_map::resolve_import_map_value_from_specifier; pub use deno_config::deno_json::BenchConfig; pub use deno_config::deno_json::ConfigFile; pub use deno_config::deno_json::FmtOptionsConfig; -pub use deno_config::deno_json::JsxImportSourceConfig; pub use deno_config::deno_json::LintRulesConfig; pub use deno_config::deno_json::ProseWrap; pub use deno_config::deno_json::TsConfig; @@ -1155,21 +1155,34 @@ impl CliOptions { self .main_module_cell .get_or_init(|| { - let main_module = match &self.flags.subcommand { + Ok(match &self.flags.subcommand { DenoSubcommand::Compile(compile_flags) => { resolve_url_or_path(&compile_flags.source_file, self.initial_cwd())? } DenoSubcommand::Eval(_) => { - resolve_url_or_path("./$deno$eval.ts", self.initial_cwd())? + resolve_url_or_path("./$deno$eval.mts", self.initial_cwd())? } DenoSubcommand::Repl(_) => { - resolve_url_or_path("./$deno$repl.ts", self.initial_cwd())? + resolve_url_or_path("./$deno$repl.mts", self.initial_cwd())? } DenoSubcommand::Run(run_flags) => { if run_flags.is_stdin() { - resolve_url_or_path("./$deno$stdin.ts", self.initial_cwd())? + resolve_url_or_path("./$deno$stdin.mts", self.initial_cwd())? } else { - resolve_url_or_path(&run_flags.script, self.initial_cwd())? + let url = + resolve_url_or_path(&run_flags.script, self.initial_cwd())?; + if self.is_node_main() + && url.scheme() == "file" + && MediaType::from_specifier(&url) == MediaType::Unknown + { + try_resolve_node_binary_main_entrypoint( + &run_flags.script, + self.initial_cwd(), + )? + .unwrap_or(url) + } else { + url + } } } DenoSubcommand::Serve(run_flags) => { @@ -1178,9 +1191,7 @@ impl CliOptions { _ => { bail!("No main module.") } - }; - - Ok(main_module) + }) }) .as_ref() .map_err(|err| deno_core::anyhow::anyhow!("{}", err)) @@ -1229,7 +1240,7 @@ impl CliOptions { // This is triggered via a secret environment variable which is used // for functionality like child_process.fork. Users should NOT depend // on this functionality. - pub fn is_npm_main(&self) -> bool { + pub fn is_node_main(&self) -> bool { NPM_PROCESS_STATE.is_some() } @@ -1607,9 +1618,11 @@ impl CliOptions { || self.workspace().has_unstable("bare-node-builtins") } - pub fn unstable_detect_cjs(&self) -> bool { - self.flags.unstable_config.detect_cjs - || self.workspace().has_unstable("detect-cjs") + pub fn detect_cjs(&self) -> bool { + // only enabled when there's a package.json in order to not have a + // perf penalty for non-npm Deno projects of searching for the closest + // package.json beside each module + self.workspace().package_jsons().next().is_some() || self.is_node_main() } fn byonm_enabled(&self) -> bool { @@ -1673,7 +1686,6 @@ impl CliOptions { "byonm", "bare-node-builtins", "fmt-component", - "detect-cjs", ]) .collect(); @@ -1811,6 +1823,36 @@ fn resolve_node_modules_folder( Ok(Some(canonicalize_path_maybe_not_exists(&path)?)) } +fn try_resolve_node_binary_main_entrypoint( + specifier: &str, + initial_cwd: &Path, +) -> Result, AnyError> { + // node allows running files at paths without a `.js` extension + // or at directories with an index.js file + let path = deno_core::normalize_path(initial_cwd.join(specifier)); + if path.is_dir() { + let index_file = path.join("index.js"); + Ok(if index_file.is_file() { + Some(deno_path_util::url_from_file_path(&index_file)?) + } else { + None + }) + } else { + let path = path.with_extension( + path + .extension() + .and_then(|s| s.to_str()) + .map(|s| format!("{}.js", s)) + .unwrap_or("js".to_string()), + ); + if path.is_file() { + Ok(Some(deno_path_util::url_from_file_path(&path)?)) + } else { + Ok(None) + } + } +} + fn resolve_import_map_specifier( maybe_import_map_path: Option<&str>, maybe_config_file: Option<&ConfigFile>, -- cgit v1.2.3 From 4e899d48cffa95617266dd8f9aef54603a87ad82 Mon Sep 17 00:00:00 2001 From: snek Date: Thu, 14 Nov 2024 13:16:28 +0100 Subject: fix: otel resiliency (#26857) Improving the breadth of collected data, and ensuring that the collected data is more likely to be successfully reported. - Use `log` crate in more places - Hook up `log` crate to otel - Switch to process-wide otel processors - Handle places that use `process::exit` Also adds a more robust testing framework, with a deterministic tracing setting. Refs: https://github.com/denoland/deno/issues/26852 --- cli/args/mod.rs | 19 ++----------------- 1 file changed, 2 insertions(+), 17 deletions(-) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 5e5bae87d..50a37b334 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -823,10 +823,8 @@ impl CliOptions { }; let msg = format!("DANGER: TLS certificate validation is disabled {}", domains); - #[allow(clippy::print_stderr)] { - // use eprintln instead of log::warn so this always gets shown - eprintln!("{}", colors::yellow(msg)); + log::error!("{}", colors::yellow(msg)); } } @@ -1131,20 +1129,7 @@ impl CliOptions { } pub fn otel_config(&self) -> Option { - if self - .flags - .unstable_config - .features - .contains(&String::from("otel")) - { - Some(OtelConfig { - runtime_name: Cow::Borrowed("deno"), - runtime_version: Cow::Borrowed(crate::version::DENO_VERSION_INFO.deno), - ..Default::default() - }) - } else { - None - } + self.flags.otel_config() } pub fn env_file_name(&self) -> Option<&String> { -- cgit v1.2.3 From 84e12386480d76e97ad85d9c5314168e7ab03e04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bartek=20Iwa=C5=84czuk?= Date: Sat, 16 Nov 2024 11:18:17 +0000 Subject: feat(task): support object notation, remove support for JSDocs (#26886) This commit changes three aspects of `deno task`: 1. Tasks can now be written using object notation like so: ```jsonc { "tasks": { "foo": "deno run foo.js", "bar": { "command": "deno run bar.js" } } ``` 2. Support for comments for tasks is now removed. Comments above tasks will no longer be printed when running `deno task`. 3. Tasks written using object notation can have "description" field that replaces support for comments above tasks: ```jsonc { "tasks": { "bar": { "description": "This is a bar task" "command": "deno run bar.js" } } ``` ``` $ deno task Available tasks: - bar // This is a bar task deno run bar.js ``` Pulled most of the changes from https://github.com/denoland/deno/pull/26467 to support "dependencies" in tasks. Additionally some cleanup was performed to make code easier to read. --------- Co-authored-by: David Sherret --- cli/args/mod.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 50a37b334..318a6ca76 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -868,12 +868,8 @@ impl CliOptions { } else { &[] }; - let config_parse_options = deno_config::deno_json::ConfigParseOptions { - include_task_comments: matches!( - flags.subcommand, - DenoSubcommand::Task(..) - ), - }; + let config_parse_options = + deno_config::deno_json::ConfigParseOptions::default(); let discover_pkg_json = flags.config_flag != ConfigFlag::Disabled && !flags.no_npm && !has_flag_env_var("DENO_NO_PACKAGE_JSON"); -- cgit v1.2.3 From cff6e280c77afb0bc42a10348eeef5360db8f361 Mon Sep 17 00:00:00 2001 From: Bhuwan Pandit Date: Sun, 17 Nov 2024 22:49:35 +0000 Subject: feat(cli): support multiple env file argument (#26527) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Closes #26425 ## Overview This PR adds support for specifying multiple environment files as arguments when using the Deno CLI. Subsequent files override pre-existing variables defined in previous files. If the same variable is defined in the environment and in the file, the value from the environment takes precedence. ## Example Usage ```bash deno run --allow-env --env-file --env-file=".env.one" --env-file=".env.two" script.ts ``` --------- Co-authored-by: Bartek Iwańczuk --- cli/args/mod.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'cli/args/mod.rs') diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 318a6ca76..ec75d7a10 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -1128,7 +1128,7 @@ impl CliOptions { self.flags.otel_config() } - pub fn env_file_name(&self) -> Option<&String> { + pub fn env_file_name(&self) -> Option<&Vec> { self.flags.env_file.as_ref() } @@ -1935,19 +1935,22 @@ pub fn config_to_deno_graph_workspace_member( }) } -fn load_env_variables_from_env_file(filename: Option<&String>) { - let Some(env_file_name) = filename else { +fn load_env_variables_from_env_file(filename: Option<&Vec>) { + let Some(env_file_names) = filename else { return; }; - match from_filename(env_file_name) { - Ok(_) => (), - Err(error) => { - match error { + + for env_file_name in env_file_names.iter().rev() { + match from_filename(env_file_name) { + Ok(_) => (), + Err(error) => { + match error { dotenvy::Error::LineParse(line, index)=> log::info!("{} Parsing failed within the specified environment file: {} at index: {} of the value: {}",colors::yellow("Warning"), env_file_name, index, line), dotenvy::Error::Io(_)=> log::info!("{} The `--env-file` flag was used, but the environment file specified '{}' was not found.",colors::yellow("Warning"),env_file_name), dotenvy::Error::EnvVar(_)=> log::info!("{} One or more of the environment variables isn't present or not unicode within the specified environment file: {}",colors::yellow("Warning"),env_file_name), _ => log::info!("{} Unknown failure occurred with the specified environment file: {}", colors::yellow("Warning"), env_file_name), } + } } } } -- cgit v1.2.3