Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 11 additions & 10 deletions cli/tools/task.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,16 @@ pub async fn execute_script(
let mut packages_task_info: Vec<PackageTaskInfo> = vec![];

let workspace = cli_options.workspace();
for folder in workspace.config_folders() {
for (folder_url, folder) in
workspace.config_folders_sorted_by_dependencies()
{
if !task_flags.recursive
&& !matches_package(folder.1, force_use_pkg_json, &package_regex)
&& !matches_package(folder, force_use_pkg_json, &package_regex)
{
continue;
}

let member_dir = workspace.resolve_member_dir(folder.0);
let member_dir = workspace.resolve_member_dir(folder_url);
let mut tasks_config = member_dir.to_tasks_config()?;
if force_use_pkg_json {
tasks_config = tasks_config.with_only_pkg_json();
Expand Down Expand Up @@ -727,27 +729,26 @@ fn print_available_tasks_workspace(
let workspace = cli_options.workspace();

let mut matched = false;
for folder in workspace.config_folders() {
if !recursive
&& !matches_package(folder.1, force_use_pkg_json, package_regex)
for (folder_url, folder) in workspace.config_folders_sorted_by_dependencies()
{
if !recursive && !matches_package(folder, force_use_pkg_json, package_regex)
{
continue;
}
matched = true;

let member_dir = workspace.resolve_member_dir(folder.0);
let member_dir = workspace.resolve_member_dir(folder_url);
let mut tasks_config = member_dir.to_tasks_config()?;

let mut pkg_name = folder
.1
.deno_json
.as_ref()
.and_then(|deno| deno.json.name.clone())
.or(folder.1.pkg_json.as_ref().and_then(|pkg| pkg.name.clone()));
.or(folder.pkg_json.as_ref().and_then(|pkg| pkg.name.clone()));

if force_use_pkg_json {
tasks_config = tasks_config.with_only_pkg_json();
pkg_name = folder.1.pkg_json.as_ref().and_then(|pkg| pkg.name.clone());
pkg_name = folder.pkg_json.as_ref().and_then(|pkg| pkg.name.clone());
}

print_available_tasks(
Expand Down
4 changes: 2 additions & 2 deletions libs/config/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ path = "lib.rs"

[features]
default = ["workspace"]
deno_json = ["jsonc-parser", "glob", "ignore", "import_map"]
deno_json = ["deno_semver", "jsonc-parser", "glob", "ignore", "import_map"]
package_json = ["deno_package_json"]
sync = ["deno_package_json/sync"]
workspace = ["deno_json", "deno_semver", "package_json"]
workspace = ["deno_json", "package_json"]

[dependencies]
boxed_error.workspace = true
Expand Down
48 changes: 48 additions & 0 deletions libs/config/deno_json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::HashSet;
use std::path::Path;
use std::path::PathBuf;

Expand All @@ -10,6 +11,7 @@ use deno_error::JsError;
use deno_path_util::url_from_file_path;
use deno_path_util::url_parent;
use deno_path_util::url_to_file_path;
use deno_semver::jsr::JsrDepPackageReq;
use import_map::ImportMapWithDiagnostics;
use indexmap::IndexMap;
use jsonc_parser::ParseResult;
Expand All @@ -28,6 +30,10 @@ use url::Url;
use crate::UrlToFilePathError;
use crate::glob::FilePatterns;
use crate::glob::PathOrPatternSet;
use crate::import_map::imports_values;
use crate::import_map::scope_values;
use crate::import_map::value_to_dep_req;
use crate::import_map::values_to_set;
use crate::util::is_skippable_io_error;

mod ts;
Expand Down Expand Up @@ -1850,6 +1856,48 @@ impl ConfigFile {
}
}
}

pub fn dependencies(&self) -> HashSet<JsrDepPackageReq> {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved from resolver/lockfile.rs

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still find it confusing that dependencies returns JsrDepPackageReq even though it's a superset that contain npm packages too

Copy link
Member Author

@dsherret dsherret Jul 17, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dependencies of JSR packages can be npm or jsr packages, so that's what it means here.

let values = imports_values(self.json.imports.as_ref())
.into_iter()
.chain(scope_values(self.json.scopes.as_ref()));
let mut set = values_to_set(values);

if let Some(serde_json::Value::Object(compiler_options)) =
&self.json.compiler_options
{
// add jsxImportSource
if let Some(serde_json::Value::String(value)) =
compiler_options.get("jsxImportSource")
{
if let Some(dep_req) = value_to_dep_req(value) {
set.insert(dep_req);
}
}
// add jsxImportSourceTypes
if let Some(serde_json::Value::String(value)) =
compiler_options.get("jsxImportSourceTypes")
{
if let Some(dep_req) = value_to_dep_req(value) {
set.insert(dep_req);
}
}
// add the dependencies in the types array
if let Some(serde_json::Value::Array(types)) =
compiler_options.get("types")
{
for value in types {
if let serde_json::Value::String(value) = value {
if let Some(dep_req) = value_to_dep_req(value) {
set.insert(dep_req);
}
}
}
}
}

set
}
}

#[cfg(test)]
Expand Down
62 changes: 62 additions & 0 deletions libs/config/import_map.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright 2018-2025 the Deno authors. MIT license.

use std::collections::HashSet;

use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference;

/// Attempts to resolve any `npm:` and `jsr:` dependencies
/// in the import map's imports and scopes.
pub fn import_map_deps(
import_map: &serde_json::Value,
) -> HashSet<JsrDepPackageReq> {
let values = imports_values(import_map.get("imports"))
.into_iter()
.chain(scope_values(import_map.get("scopes")));
values_to_set(values)
}

pub(crate) fn imports_values(
value: Option<&serde_json::Value>,
) -> Vec<&String> {
let Some(obj) = value.and_then(|v| v.as_object()) else {
return Vec::new();
};
let mut items = Vec::with_capacity(obj.len());
for value in obj.values() {
if let serde_json::Value::String(value) = value {
items.push(value);
}
}
items
}

pub(crate) fn scope_values(value: Option<&serde_json::Value>) -> Vec<&String> {
let Some(obj) = value.and_then(|v| v.as_object()) else {
return Vec::new();
};
obj.values().flat_map(|v| imports_values(Some(v))).collect()
}

pub(crate) fn values_to_set<'a>(
values: impl Iterator<Item = &'a String>,
) -> HashSet<JsrDepPackageReq> {
let mut entries = HashSet::new();
for value in values {
if let Some(dep_req) = value_to_dep_req(value) {
entries.insert(dep_req);
}
}
entries
}

pub(crate) fn value_to_dep_req(value: &str) -> Option<JsrDepPackageReq> {
match JsrPackageReqReference::from_str(value) {
Ok(req_ref) => Some(JsrDepPackageReq::jsr(req_ref.into_inner().req)),
_ => match NpmPackageReqReference::from_str(value) {
Ok(req_ref) => Some(JsrDepPackageReq::npm(req_ref.into_inner().req)),
_ => None,
},
}
}
2 changes: 2 additions & 0 deletions libs/config/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub mod deno_json;
#[cfg(feature = "deno_json")]
pub mod glob;
#[cfg(feature = "deno_json")]
pub mod import_map;
#[cfg(feature = "deno_json")]
mod sync;
#[cfg(feature = "deno_json")]
mod util;
Expand Down
Loading
Loading