mirror of
https://github.com/denoland/deno.git
synced 2024-11-24 15:19:26 -05:00
feat(lockfile): track JSR and npm dependencies in config file (#22004)
See overview in https://github.com/denoland/deno_lockfile/pull/13
This commit is contained in:
parent
d20c9e75d1
commit
69d5f136ba
18 changed files with 409 additions and 123 deletions
34
Cargo.lock
generated
34
Cargo.lock
generated
|
@ -1004,7 +1004,7 @@ dependencies = [
|
||||||
"libz-sys",
|
"libz-sys",
|
||||||
"log",
|
"log",
|
||||||
"lsp-types",
|
"lsp-types",
|
||||||
"monch 0.5.0",
|
"monch",
|
||||||
"napi_sym",
|
"napi_sym",
|
||||||
"nix 0.26.2",
|
"nix 0.26.2",
|
||||||
"notify",
|
"notify",
|
||||||
|
@ -1352,9 +1352,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_graph"
|
name = "deno_graph"
|
||||||
version = "0.63.3"
|
version = "0.63.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7cf16929b6a267be4bc535877303a3a36b3595b6b27543baa07d3b77b679d92"
|
checksum = "be751db3da720bcd35d42f9c0967a04cafd52d554d79262426d1c00179b0c085"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1365,7 +1365,7 @@ dependencies = [
|
||||||
"import_map",
|
"import_map",
|
||||||
"indexmap",
|
"indexmap",
|
||||||
"log",
|
"log",
|
||||||
"monch 0.4.3",
|
"monch",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"parking_lot 0.12.1",
|
"parking_lot 0.12.1",
|
||||||
"regex",
|
"regex",
|
||||||
|
@ -1478,9 +1478,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_lockfile"
|
name = "deno_lockfile"
|
||||||
version = "0.17.2"
|
version = "0.18.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8cd29f62e6dec60e585f579df3e9c2fc562aadf881319152974bc442a9042077"
|
checksum = "dfe06eda519ed05b69da567bcba1d728c482fd553ddaa2ffe008468158da6de0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ring",
|
"ring",
|
||||||
"serde",
|
"serde",
|
||||||
|
@ -1606,9 +1606,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_npm"
|
name = "deno_npm"
|
||||||
version = "0.15.3"
|
version = "0.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "718b0b55031643de7808f8b426661b22a685820f1f459e028776bcc49e07b881"
|
checksum = "376262760b173ff01f8f5d05d58a64f6d863472396afb5582590fa0949342854"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
|
@ -1616,7 +1616,7 @@ dependencies = [
|
||||||
"deno_semver",
|
"deno_semver",
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"monch 0.4.3",
|
"monch",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
]
|
]
|
||||||
|
@ -1706,7 +1706,7 @@ version = "0.5.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b49e14effd9df8ed261f7a1a34ac19bbaf0fa940c59bd19a6d8313cf41525e1c"
|
checksum = "b49e14effd9df8ed261f7a1a34ac19bbaf0fa940c59bd19a6d8313cf41525e1c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"monch 0.5.0",
|
"monch",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"serde",
|
"serde",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
|
@ -1722,7 +1722,7 @@ dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"futures",
|
"futures",
|
||||||
"glob",
|
"glob",
|
||||||
"monch 0.5.0",
|
"monch",
|
||||||
"os_pipe",
|
"os_pipe",
|
||||||
"path-dedot",
|
"path-dedot",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
@ -2349,9 +2349,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "eszip"
|
name = "eszip"
|
||||||
version = "0.57.0"
|
version = "0.58.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e081e749cb42d7e52b9a066564b86c70e586614d5de684080a2be861f35a0721"
|
checksum = "214f3a524473bb2c76385c02fdada6c2791ba5e07e9ac72a6c1e373d665b1680"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64",
|
"base64",
|
||||||
|
@ -3775,12 +3775,6 @@ dependencies = [
|
||||||
"windows-sys 0.48.0",
|
"windows-sys 0.48.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "monch"
|
|
||||||
version = "0.4.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4519a88847ba2d5ead3dc53f1060ec6a571de93f325d9c5c4968147382b1cbc3"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "monch"
|
name = "monch"
|
||||||
version = "0.5.0"
|
version = "0.5.0"
|
||||||
|
@ -6173,7 +6167,7 @@ dependencies = [
|
||||||
"lazy-regex",
|
"lazy-regex",
|
||||||
"libc",
|
"libc",
|
||||||
"lsp-types",
|
"lsp-types",
|
||||||
"monch 0.5.0",
|
"monch",
|
||||||
"nix 0.26.2",
|
"nix 0.26.2",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"os_pipe",
|
"os_pipe",
|
||||||
|
|
|
@ -48,7 +48,7 @@ deno_runtime = { version = "0.140.0", path = "./runtime" }
|
||||||
napi_sym = { version = "0.62.0", path = "./cli/napi/sym" }
|
napi_sym = { version = "0.62.0", path = "./cli/napi/sym" }
|
||||||
deno_bench_util = { version = "0.126.0", path = "./bench_util" }
|
deno_bench_util = { version = "0.126.0", path = "./bench_util" }
|
||||||
test_util = { path = "./test_util" }
|
test_util = { path = "./test_util" }
|
||||||
deno_lockfile = "0.17.2"
|
deno_lockfile = "0.18.0"
|
||||||
deno_media_type = { version = "0.1.1", features = ["module_specifier"] }
|
deno_media_type = { version = "0.1.1", features = ["module_specifier"] }
|
||||||
|
|
||||||
denokv_proto = "0.5.0"
|
denokv_proto = "0.5.0"
|
||||||
|
|
|
@ -59,14 +59,14 @@ deno_config = "=0.8.1"
|
||||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_doc = { version = "=0.93.0", features = ["html"] }
|
deno_doc = { version = "=0.93.0", features = ["html"] }
|
||||||
deno_emit = "=0.33.0"
|
deno_emit = "=0.33.0"
|
||||||
deno_graph = "=0.63.3"
|
deno_graph = "=0.63.4"
|
||||||
deno_lint = { version = "=0.53.0", features = ["docs"] }
|
deno_lint = { version = "=0.53.0", features = ["docs"] }
|
||||||
deno_lockfile.workspace = true
|
deno_lockfile.workspace = true
|
||||||
deno_npm = "=0.15.3"
|
deno_npm = "=0.16.0"
|
||||||
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_runtime = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_semver = "=0.5.4"
|
deno_semver = "=0.5.4"
|
||||||
deno_task_shell = "=0.14.3"
|
deno_task_shell = "=0.14.3"
|
||||||
eszip = "=0.57.0"
|
eszip = "=0.58.0"
|
||||||
napi_sym.workspace = true
|
napi_sym.workspace = true
|
||||||
|
|
||||||
async-trait.workspace = true
|
async-trait.workspace = true
|
||||||
|
|
|
@ -1344,6 +1344,10 @@ impl CliOptions {
|
||||||
self.flags.no_npm
|
self.flags.no_npm
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn no_config(&self) -> bool {
|
||||||
|
self.flags.config_flag == deno_config::ConfigFlag::Disabled
|
||||||
|
}
|
||||||
|
|
||||||
pub fn permissions_options(&self) -> PermissionsOptions {
|
pub fn permissions_options(&self) -> PermissionsOptions {
|
||||||
PermissionsOptions {
|
PermissionsOptions {
|
||||||
allow_env: self.flags.allow_env.clone(),
|
allow_env: self.flags.allow_env.clone(),
|
||||||
|
|
|
@ -6,7 +6,6 @@ use std::path::PathBuf;
|
||||||
use deno_core::anyhow::bail;
|
use deno_core::anyhow::bail;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
use deno_npm::registry::parse_dep_entry_name_and_raw_version;
|
use deno_npm::registry::parse_dep_entry_name_and_raw_version;
|
||||||
use deno_npm::registry::PackageDepNpmSchemeValueParseError;
|
|
||||||
use deno_runtime::deno_node::PackageJson;
|
use deno_runtime::deno_node::PackageJson;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
use deno_semver::VersionReq;
|
use deno_semver::VersionReq;
|
||||||
|
@ -16,8 +15,6 @@ use thiserror::Error;
|
||||||
|
|
||||||
#[derive(Debug, Error, Clone)]
|
#[derive(Debug, Error, Clone)]
|
||||||
pub enum PackageJsonDepValueParseError {
|
pub enum PackageJsonDepValueParseError {
|
||||||
#[error(transparent)]
|
|
||||||
SchemeValue(#[from] PackageDepNpmSchemeValueParseError),
|
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
Specifier(#[from] VersionReqSpecifierParseError),
|
Specifier(#[from] VersionReqSpecifierParseError),
|
||||||
#[error("Not implemented scheme '{scheme}'")]
|
#[error("Not implemented scheme '{scheme}'")]
|
||||||
|
@ -39,7 +36,7 @@ impl PackageJsonDepsProvider {
|
||||||
self.0.as_ref()
|
self.0.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn reqs(&self) -> Vec<&PackageReq> {
|
pub fn reqs(&self) -> Option<Vec<&PackageReq>> {
|
||||||
match &self.0 {
|
match &self.0 {
|
||||||
Some(deps) => {
|
Some(deps) => {
|
||||||
let mut package_reqs = deps
|
let mut package_reqs = deps
|
||||||
|
@ -47,9 +44,9 @@ impl PackageJsonDepsProvider {
|
||||||
.filter_map(|r| r.as_ref().ok())
|
.filter_map(|r| r.as_ref().ok())
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
package_reqs.sort(); // deterministic resolution
|
package_reqs.sort(); // deterministic resolution
|
||||||
package_reqs
|
Some(package_reqs)
|
||||||
}
|
}
|
||||||
None => Vec::new(),
|
None => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -77,9 +74,7 @@ pub fn get_local_package_json_version_reqs(
|
||||||
scheme: value.split(':').next().unwrap().to_string(),
|
scheme: value.split(':').next().unwrap().to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let (name, version_req) = parse_dep_entry_name_and_raw_version(key, value)
|
let (name, version_req) = parse_dep_entry_name_and_raw_version(key, value);
|
||||||
.map_err(PackageJsonDepValueParseError::SchemeValue)?;
|
|
||||||
|
|
||||||
let result = VersionReq::parse_from_specifier(version_req);
|
let result = VersionReq::parse_from_specifier(version_req);
|
||||||
match result {
|
match result {
|
||||||
Ok(version_req) => Ok(PackageReq {
|
Ok(version_req) => Ok(PackageReq {
|
||||||
|
@ -159,27 +154,6 @@ mod test {
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_dep_entry_name_and_raw_version() {
|
|
||||||
let cases = [
|
|
||||||
("test", "^1.2", Ok(("test", "^1.2"))),
|
|
||||||
("test", "1.x - 2.6", Ok(("test", "1.x - 2.6"))),
|
|
||||||
("test", "npm:package@^1.2", Ok(("package", "^1.2"))),
|
|
||||||
(
|
|
||||||
"test",
|
|
||||||
"npm:package",
|
|
||||||
Err("Could not find @ symbol in npm url 'npm:package'"),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
for (key, value, expected_result) in cases {
|
|
||||||
let result = parse_dep_entry_name_and_raw_version(key, value);
|
|
||||||
match result {
|
|
||||||
Ok(result) => assert_eq!(result, expected_result.unwrap()),
|
|
||||||
Err(err) => assert_eq!(err.to_string(), expected_result.err().unwrap()),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_local_package_json_version_reqs_for_tests(
|
fn get_local_package_json_version_reqs_for_tests(
|
||||||
package_json: &PackageJson,
|
package_json: &PackageJson,
|
||||||
) -> IndexMap<String, Result<PackageReq, String>> {
|
) -> IndexMap<String, Result<PackageReq, String>> {
|
||||||
|
|
|
@ -44,6 +44,8 @@ use crate::standalone::DenoCompileBinaryWriter;
|
||||||
use crate::tools::check::TypeChecker;
|
use crate::tools::check::TypeChecker;
|
||||||
use crate::util::file_watcher::WatcherCommunicator;
|
use crate::util::file_watcher::WatcherCommunicator;
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
|
use crate::util::import_map::deno_json_deps;
|
||||||
|
use crate::util::import_map::import_map_deps;
|
||||||
use crate::util::progress_bar::ProgressBar;
|
use crate::util::progress_bar::ProgressBar;
|
||||||
use crate::util::progress_bar::ProgressBarStyle;
|
use crate::util::progress_bar::ProgressBarStyle;
|
||||||
use crate::worker::CliMainWorkerFactory;
|
use crate::worker::CliMainWorkerFactory;
|
||||||
|
@ -54,12 +56,14 @@ use deno_core::parking_lot::Mutex;
|
||||||
use deno_core::FeatureChecker;
|
use deno_core::FeatureChecker;
|
||||||
|
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
|
use deno_lockfile::WorkspaceMemberConfig;
|
||||||
use deno_runtime::deno_fs;
|
use deno_runtime::deno_fs;
|
||||||
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
use deno_runtime::deno_node::analyze::NodeCodeTranslator;
|
||||||
use deno_runtime::deno_node::NodeResolver;
|
use deno_runtime::deno_node::NodeResolver;
|
||||||
use deno_runtime::deno_tls::RootCertStoreProvider;
|
use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
use deno_runtime::deno_web::BlobStore;
|
use deno_runtime::deno_web::BlobStore;
|
||||||
use deno_runtime::inspector_server::InspectorServer;
|
use deno_runtime::inspector_server::InspectorServer;
|
||||||
|
use deno_semver::package::PackageNv;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
|
@ -289,10 +293,84 @@ impl CliFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_lockfile(&self) -> &Option<Arc<Mutex<Lockfile>>> {
|
pub fn maybe_lockfile(&self) -> &Option<Arc<Mutex<Lockfile>>> {
|
||||||
self
|
self.services.lockfile.get_or_init(|| {
|
||||||
.services
|
let maybe_lockfile = self.options.maybe_lockfile();
|
||||||
.lockfile
|
|
||||||
.get_or_init(|| self.options.maybe_lockfile())
|
// initialize the lockfile with the workspace's configuration
|
||||||
|
if let Some(lockfile) = &maybe_lockfile {
|
||||||
|
let package_json_deps = self
|
||||||
|
.package_json_deps_provider()
|
||||||
|
.reqs()
|
||||||
|
.map(|reqs| reqs.into_iter().map(|s| format!("npm:{}", s)).collect())
|
||||||
|
.unwrap_or_default();
|
||||||
|
let mut lockfile = lockfile.lock();
|
||||||
|
let config = match self.options.maybe_workspace_config() {
|
||||||
|
Some(workspace_config) => deno_lockfile::WorkspaceConfig {
|
||||||
|
root: WorkspaceMemberConfig {
|
||||||
|
package_json_deps,
|
||||||
|
dependencies: import_map_deps(
|
||||||
|
&workspace_config.base_import_map_value,
|
||||||
|
)
|
||||||
|
.into_iter()
|
||||||
|
.map(|req| req.to_string())
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
members: workspace_config
|
||||||
|
.members
|
||||||
|
.iter()
|
||||||
|
.map(|member| {
|
||||||
|
(
|
||||||
|
member.package_name.clone(),
|
||||||
|
WorkspaceMemberConfig {
|
||||||
|
package_json_deps: Default::default(),
|
||||||
|
dependencies: deno_json_deps(&member.config_file)
|
||||||
|
.into_iter()
|
||||||
|
.map(|req| req.to_string())
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
},
|
||||||
|
None => deno_lockfile::WorkspaceConfig {
|
||||||
|
root: WorkspaceMemberConfig {
|
||||||
|
package_json_deps,
|
||||||
|
dependencies: self
|
||||||
|
.options
|
||||||
|
.maybe_config_file()
|
||||||
|
.as_ref()
|
||||||
|
.map(|config| {
|
||||||
|
deno_json_deps(config)
|
||||||
|
.into_iter()
|
||||||
|
.map(|req| req.to_string())
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.unwrap_or_default(),
|
||||||
|
},
|
||||||
|
members: Default::default(),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
lockfile.set_workspace_config(
|
||||||
|
deno_lockfile::SetWorkspaceConfigOptions {
|
||||||
|
no_npm: self.options.no_npm(),
|
||||||
|
no_config: self.options.no_config(),
|
||||||
|
config,
|
||||||
|
nv_to_jsr_url: |nv| {
|
||||||
|
let nv = PackageNv::from_str(nv).ok()?;
|
||||||
|
Some(
|
||||||
|
deno_graph::source::recommended_registry_package_url(
|
||||||
|
crate::args::deno_registry_url(),
|
||||||
|
&nv,
|
||||||
|
)
|
||||||
|
.to_string(),
|
||||||
|
)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
maybe_lockfile
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn npm_resolver(
|
pub async fn npm_resolver(
|
||||||
|
@ -320,7 +398,7 @@ impl CliFactory {
|
||||||
Some(snapshot) => {
|
Some(snapshot) => {
|
||||||
CliNpmResolverManagedSnapshotOption::Specified(Some(snapshot))
|
CliNpmResolverManagedSnapshotOption::Specified(Some(snapshot))
|
||||||
}
|
}
|
||||||
None => match self.maybe_lockfile() {
|
None => match self.maybe_lockfile().as_ref() {
|
||||||
Some(lockfile) => {
|
Some(lockfile) => {
|
||||||
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
CliNpmResolverManagedSnapshotOption::ResolveFromLockfile(
|
||||||
lockfile.clone(),
|
lockfile.clone(),
|
||||||
|
|
|
@ -504,6 +504,10 @@ impl ModuleGraphBuilder {
|
||||||
format!("jsr:{}", to),
|
format!("jsr:{}", to),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
for (name, deps) in graph.packages.package_deps() {
|
||||||
|
lockfile
|
||||||
|
.insert_package_deps(name.to_string(), deps.map(|s| s.to_string()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
10
cli/main.rs
10
cli/main.rs
|
@ -38,6 +38,7 @@ use deno_core::error::AnyError;
|
||||||
use deno_core::error::JsError;
|
use deno_core::error::JsError;
|
||||||
use deno_core::futures::FutureExt;
|
use deno_core::futures::FutureExt;
|
||||||
use deno_core::unsync::JoinHandle;
|
use deno_core::unsync::JoinHandle;
|
||||||
|
use deno_npm::resolution::SnapshotFromLockfileError;
|
||||||
use deno_runtime::colors;
|
use deno_runtime::colors;
|
||||||
use deno_runtime::fmt_errors::format_js_error;
|
use deno_runtime::fmt_errors::format_js_error;
|
||||||
use deno_runtime::tokio_util::create_and_run_current_thread_with_maybe_metrics;
|
use deno_runtime::tokio_util::create_and_run_current_thread_with_maybe_metrics;
|
||||||
|
@ -261,7 +262,14 @@ fn unwrap_or_exit<T>(result: Result<T, AnyError>) -> T {
|
||||||
|
|
||||||
if let Some(e) = error.downcast_ref::<JsError>() {
|
if let Some(e) = error.downcast_ref::<JsError>() {
|
||||||
error_string = format_js_error(e);
|
error_string = format_js_error(e);
|
||||||
} else if let Some(e) = error.downcast_ref::<args::LockfileError>() {
|
} else if let Some(args::LockfileError::IntegrityCheckFailed(e)) =
|
||||||
|
error.downcast_ref::<args::LockfileError>()
|
||||||
|
{
|
||||||
|
error_string = e.to_string();
|
||||||
|
error_code = 10;
|
||||||
|
} else if let Some(SnapshotFromLockfileError::IntegrityCheckFailed(e)) =
|
||||||
|
error.downcast_ref::<SnapshotFromLockfileError>()
|
||||||
|
{
|
||||||
error_string = e.to_string();
|
error_string = e.to_string();
|
||||||
error_code = 10;
|
error_code = 10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,7 +82,7 @@ impl PackageJsonDepsInstaller {
|
||||||
return Ok(()); // already installed by something else
|
return Ok(()); // already installed by something else
|
||||||
}
|
}
|
||||||
|
|
||||||
let package_reqs = inner.deps_provider.reqs();
|
let package_reqs = inner.deps_provider.reqs().unwrap_or_default();
|
||||||
|
|
||||||
// check if something needs resolving before bothering to load all
|
// check if something needs resolving before bothering to load all
|
||||||
// the package information (which is slow)
|
// the package information (which is slow)
|
||||||
|
|
|
@ -225,12 +225,20 @@ async fn snapshot_from_lockfile(
|
||||||
lockfile: Arc<Mutex<Lockfile>>,
|
lockfile: Arc<Mutex<Lockfile>>,
|
||||||
api: &dyn NpmRegistryApi,
|
api: &dyn NpmRegistryApi,
|
||||||
) -> Result<ValidSerializedNpmResolutionSnapshot, AnyError> {
|
) -> Result<ValidSerializedNpmResolutionSnapshot, AnyError> {
|
||||||
let incomplete_snapshot = {
|
let (incomplete_snapshot, skip_integrity_check) = {
|
||||||
let lock = lockfile.lock();
|
let lock = lockfile.lock();
|
||||||
deno_npm::resolution::incomplete_snapshot_from_lockfile(&lock)?
|
(
|
||||||
|
deno_npm::resolution::incomplete_snapshot_from_lockfile(&lock)?,
|
||||||
|
lock.overwrite,
|
||||||
|
)
|
||||||
};
|
};
|
||||||
let snapshot =
|
let snapshot = deno_npm::resolution::snapshot_from_lockfile(
|
||||||
deno_npm::resolution::snapshot_from_lockfile(incomplete_snapshot, api)
|
deno_npm::resolution::SnapshotFromLockfileParams {
|
||||||
|
incomplete_snapshot,
|
||||||
|
api,
|
||||||
|
skip_integrity_check,
|
||||||
|
},
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(snapshot)
|
Ok(snapshot)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use deno_core::parking_lot::RwLock;
|
||||||
use deno_lockfile::NpmPackageDependencyLockfileInfo;
|
use deno_lockfile::NpmPackageDependencyLockfileInfo;
|
||||||
use deno_lockfile::NpmPackageLockfileInfo;
|
use deno_lockfile::NpmPackageLockfileInfo;
|
||||||
use deno_npm::registry::NpmPackageInfo;
|
use deno_npm::registry::NpmPackageInfo;
|
||||||
use deno_npm::registry::NpmPackageVersionDistInfoIntegrity;
|
|
||||||
use deno_npm::registry::NpmRegistryApi;
|
use deno_npm::registry::NpmRegistryApi;
|
||||||
use deno_npm::resolution::NpmPackageVersionResolutionError;
|
use deno_npm::resolution::NpmPackageVersionResolutionError;
|
||||||
use deno_npm::resolution::NpmPackagesPartitioned;
|
use deno_npm::resolution::NpmPackagesPartitioned;
|
||||||
|
@ -388,21 +387,6 @@ fn populate_lockfile_from_snapshot(
|
||||||
fn npm_package_to_lockfile_info(
|
fn npm_package_to_lockfile_info(
|
||||||
pkg: &NpmResolutionPackage,
|
pkg: &NpmResolutionPackage,
|
||||||
) -> NpmPackageLockfileInfo {
|
) -> NpmPackageLockfileInfo {
|
||||||
fn integrity_for_lockfile(
|
|
||||||
integrity: NpmPackageVersionDistInfoIntegrity,
|
|
||||||
) -> String {
|
|
||||||
match integrity {
|
|
||||||
NpmPackageVersionDistInfoIntegrity::Integrity {
|
|
||||||
algorithm,
|
|
||||||
base64_hash,
|
|
||||||
} => format!("{}-{}", algorithm, base64_hash),
|
|
||||||
NpmPackageVersionDistInfoIntegrity::UnknownIntegrity(integrity) => {
|
|
||||||
integrity.to_string()
|
|
||||||
}
|
|
||||||
NpmPackageVersionDistInfoIntegrity::LegacySha1Hex(hex) => hex.to_string(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let dependencies = pkg
|
let dependencies = pkg
|
||||||
.dependencies
|
.dependencies
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -415,7 +399,7 @@ fn npm_package_to_lockfile_info(
|
||||||
NpmPackageLockfileInfo {
|
NpmPackageLockfileInfo {
|
||||||
display_id: pkg.id.nv.to_string(),
|
display_id: pkg.id.nv.to_string(),
|
||||||
serialized_id: pkg.id.as_serialized(),
|
serialized_id: pkg.id.as_serialized(),
|
||||||
integrity: integrity_for_lockfile(pkg.dist.integrity()),
|
integrity: pkg.dist.integrity().for_lockfile(),
|
||||||
dependencies,
|
dependencies,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,6 @@ use deno_core::futures::AsyncReadExt;
|
||||||
use deno_core::futures::AsyncSeekExt;
|
use deno_core::futures::AsyncSeekExt;
|
||||||
use deno_core::serde_json;
|
use deno_core::serde_json;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_npm::registry::PackageDepNpmSchemeValueParseError;
|
|
||||||
use deno_npm::NpmSystemInfo;
|
use deno_npm::NpmSystemInfo;
|
||||||
use deno_runtime::permissions::PermissionsOptions;
|
use deno_runtime::permissions::PermissionsOptions;
|
||||||
use deno_semver::package::PackageReq;
|
use deno_semver::package::PackageReq;
|
||||||
|
@ -51,7 +50,6 @@ const MAGIC_TRAILER: &[u8; 8] = b"d3n0l4nd";
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
enum SerializablePackageJsonDepValueParseError {
|
enum SerializablePackageJsonDepValueParseError {
|
||||||
SchemeValue(String),
|
|
||||||
Specifier(String),
|
Specifier(String),
|
||||||
Unsupported { scheme: String },
|
Unsupported { scheme: String },
|
||||||
}
|
}
|
||||||
|
@ -59,9 +57,6 @@ enum SerializablePackageJsonDepValueParseError {
|
||||||
impl SerializablePackageJsonDepValueParseError {
|
impl SerializablePackageJsonDepValueParseError {
|
||||||
pub fn from_err(err: PackageJsonDepValueParseError) -> Self {
|
pub fn from_err(err: PackageJsonDepValueParseError) -> Self {
|
||||||
match err {
|
match err {
|
||||||
PackageJsonDepValueParseError::SchemeValue(err) => {
|
|
||||||
Self::SchemeValue(err.value)
|
|
||||||
}
|
|
||||||
PackageJsonDepValueParseError::Specifier(err) => {
|
PackageJsonDepValueParseError::Specifier(err) => {
|
||||||
Self::Specifier(err.source.to_string())
|
Self::Specifier(err.source.to_string())
|
||||||
}
|
}
|
||||||
|
@ -73,11 +68,6 @@ impl SerializablePackageJsonDepValueParseError {
|
||||||
|
|
||||||
pub fn into_err(self) -> PackageJsonDepValueParseError {
|
pub fn into_err(self) -> PackageJsonDepValueParseError {
|
||||||
match self {
|
match self {
|
||||||
SerializablePackageJsonDepValueParseError::SchemeValue(value) => {
|
|
||||||
PackageJsonDepValueParseError::SchemeValue(
|
|
||||||
PackageDepNpmSchemeValueParseError { value },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
SerializablePackageJsonDepValueParseError::Specifier(source) => {
|
SerializablePackageJsonDepValueParseError::Specifier(source) => {
|
||||||
PackageJsonDepValueParseError::Specifier(
|
PackageJsonDepValueParseError::Specifier(
|
||||||
VersionReqSpecifierParseError {
|
VersionReqSpecifierParseError {
|
||||||
|
|
|
@ -256,7 +256,7 @@ itest!(import_map {
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(lock_file {
|
itest!(lock_file_integrity_failure {
|
||||||
args: "run --allow-read --allow-env --lock npm/lock_file/lock.json npm/lock_file/main.js",
|
args: "run --allow-read --allow-env --lock npm/lock_file/lock.json npm/lock_file/main.js",
|
||||||
output: "npm/lock_file/main.out",
|
output: "npm/lock_file/main.out",
|
||||||
envs: env_vars_for_npm_tests(),
|
envs: env_vars_for_npm_tests(),
|
||||||
|
@ -1517,10 +1517,9 @@ fn lock_file_lock_write() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn auto_discover_lock_file() {
|
fn auto_discover_lock_file() {
|
||||||
let _server = http_server();
|
let context = TestContextBuilder::for_npm().use_temp_cwd().build();
|
||||||
|
|
||||||
let deno_dir = util::new_deno_dir();
|
let temp_dir = context.temp_dir();
|
||||||
let temp_dir = util::TempDir::new();
|
|
||||||
|
|
||||||
// write empty config file
|
// write empty config file
|
||||||
temp_dir.write("deno.json", "{}");
|
temp_dir.write("deno.json", "{}");
|
||||||
|
@ -1541,25 +1540,26 @@ fn auto_discover_lock_file() {
|
||||||
}"#;
|
}"#;
|
||||||
temp_dir.write("deno.lock", lock_file_content);
|
temp_dir.write("deno.lock", lock_file_content);
|
||||||
|
|
||||||
let deno = util::deno_cmd_with_deno_dir(&deno_dir)
|
let output = context
|
||||||
.current_dir(temp_dir.path())
|
.new_command()
|
||||||
.arg("run")
|
.args("run --unstable -A npm:@denotest/bin/cli-esm test")
|
||||||
.arg("--unstable")
|
.run();
|
||||||
.arg("-A")
|
output
|
||||||
.arg("npm:@denotest/bin/cli-esm")
|
.assert_matches_text(
|
||||||
.arg("test")
|
r#"Download http://localhost:4545/npm/registry/@denotest/bin
|
||||||
.envs(env_vars_for_npm_tests())
|
error: Integrity check failed for npm package: "@denotest/bin@1.0.0". Unable to verify that the package
|
||||||
.piped_output()
|
is the same as when the lockfile was generated.
|
||||||
.spawn()
|
|
||||||
.unwrap();
|
|
||||||
let output = deno.wait_with_output().unwrap();
|
|
||||||
assert!(!output.status.success());
|
|
||||||
assert_eq!(output.status.code(), Some(10));
|
|
||||||
|
|
||||||
let stderr = String::from_utf8(output.stderr).unwrap();
|
Actual: sha512-[WILDCARD]
|
||||||
assert!(stderr.contains(
|
Expected: sha512-foobar
|
||||||
"Integrity check failed for npm package: \"@denotest/bin@1.0.0\""
|
|
||||||
));
|
This could be caused by:
|
||||||
|
* the lock file may be corrupt
|
||||||
|
* the source itself may be corrupt
|
||||||
|
|
||||||
|
Use "--lock-write" flag to regenerate the lockfile at "[WILDCARD]deno.lock".
|
||||||
|
"#)
|
||||||
|
.assert_exit_code(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -1017,6 +1017,170 @@ fn lock_redirects() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn lock_deno_json_package_json_deps() {
|
||||||
|
let context = TestContextBuilder::new()
|
||||||
|
.use_temp_cwd()
|
||||||
|
.use_http_server()
|
||||||
|
.add_npm_env_vars()
|
||||||
|
.add_jsr_env_vars()
|
||||||
|
.build();
|
||||||
|
let temp_dir = context.temp_dir().path();
|
||||||
|
let deno_json = temp_dir.join("deno.json");
|
||||||
|
let package_json = temp_dir.join("package.json");
|
||||||
|
|
||||||
|
// add a jsr and npm dependency
|
||||||
|
deno_json.write_json(&json!({
|
||||||
|
"imports": {
|
||||||
|
"esm-basic": "npm:@denotest/esm-basic",
|
||||||
|
"module_graph": "jsr:@denotest/module_graph@1.4",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
let main_ts = temp_dir.join("main.ts");
|
||||||
|
main_ts.write("import 'esm-basic'; import 'module_graph';");
|
||||||
|
context
|
||||||
|
.new_command()
|
||||||
|
.args("cache main.ts")
|
||||||
|
.run()
|
||||||
|
.skip_output_check();
|
||||||
|
let lockfile = temp_dir.join("deno.lock");
|
||||||
|
// todo(dsherret): it would be nice if the test server didn't produce
|
||||||
|
// different hashes depending on what operating system it's running on
|
||||||
|
let esm_basic_integrity = lockfile
|
||||||
|
.read_json_value()
|
||||||
|
.get("packages")
|
||||||
|
.unwrap()
|
||||||
|
.get("npm")
|
||||||
|
.unwrap()
|
||||||
|
.get("@denotest/esm-basic@1.0.0")
|
||||||
|
.unwrap()
|
||||||
|
.get("integrity")
|
||||||
|
.unwrap()
|
||||||
|
.as_str()
|
||||||
|
.unwrap()
|
||||||
|
.to_string();
|
||||||
|
lockfile.assert_matches_json(json!({
|
||||||
|
"version": "3",
|
||||||
|
"packages": {
|
||||||
|
"specifiers": {
|
||||||
|
"jsr:@denotest/module_graph@1.4": "jsr:@denotest/module_graph@1.4.0",
|
||||||
|
"npm:@denotest/esm-basic": "npm:@denotest/esm-basic@1.0.0"
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"@denotest/esm-basic@1.0.0": {
|
||||||
|
"integrity": esm_basic_integrity,
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"http://localhost:4545/jsr/registry/@denotest/module_graph/1.4.0/mod.ts": "5b0ce36e08d759118200d8b4627627b5a89b6261fbb0598e6961a6b287abb699",
|
||||||
|
"http://localhost:4545/jsr/registry/@denotest/module_graph/1.4.0/other.ts": "9ce27ca439cb0e218b6e1ec26c043dbc0b54c9babc4cb432df478dd1721faade"
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@denotest/module_graph@1.4",
|
||||||
|
"npm:@denotest/esm-basic"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// now remove the npm dependency from the deno.json and move
|
||||||
|
// it to a package.json that uses an alias
|
||||||
|
deno_json.write_json(&json!({
|
||||||
|
"imports": {
|
||||||
|
"module_graph": "jsr:@denotest/module_graph@1.4",
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
package_json.write_json(&json!({
|
||||||
|
"dependencies": {
|
||||||
|
"esm-basic": "npm:@denotest/esm-basic"
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
context
|
||||||
|
.new_command()
|
||||||
|
.args("cache main.ts")
|
||||||
|
.run()
|
||||||
|
.skip_output_check();
|
||||||
|
main_ts.write("import 'module_graph';");
|
||||||
|
context
|
||||||
|
.new_command()
|
||||||
|
// ensure this doesn't clear out packageJson below
|
||||||
|
.args("cache --no-npm main.ts")
|
||||||
|
.run()
|
||||||
|
.skip_output_check();
|
||||||
|
lockfile.assert_matches_json(json!({
|
||||||
|
"version": "3",
|
||||||
|
"packages": {
|
||||||
|
"specifiers": {
|
||||||
|
"jsr:@denotest/module_graph@1.4": "jsr:@denotest/module_graph@1.4.0",
|
||||||
|
"npm:@denotest/esm-basic": "npm:@denotest/esm-basic@1.0.0"
|
||||||
|
},
|
||||||
|
"npm": {
|
||||||
|
"@denotest/esm-basic@1.0.0": {
|
||||||
|
"integrity": esm_basic_integrity,
|
||||||
|
"dependencies": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"http://localhost:4545/jsr/registry/@denotest/module_graph/1.4.0/mod.ts": "5b0ce36e08d759118200d8b4627627b5a89b6261fbb0598e6961a6b287abb699",
|
||||||
|
"http://localhost:4545/jsr/registry/@denotest/module_graph/1.4.0/other.ts": "9ce27ca439cb0e218b6e1ec26c043dbc0b54c9babc4cb432df478dd1721faade"
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@denotest/module_graph@1.4"
|
||||||
|
],
|
||||||
|
"packageJson": {
|
||||||
|
"dependencies": [
|
||||||
|
"npm:@denotest/esm-basic"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// now remove the package.json
|
||||||
|
package_json.remove_file();
|
||||||
|
|
||||||
|
// cache and it will remove the package.json
|
||||||
|
context
|
||||||
|
.new_command()
|
||||||
|
.args("cache main.ts")
|
||||||
|
.run()
|
||||||
|
.skip_output_check();
|
||||||
|
lockfile.assert_matches_json(json!({
|
||||||
|
"version": "3",
|
||||||
|
"packages": {
|
||||||
|
"specifiers": {
|
||||||
|
"jsr:@denotest/module_graph@1.4": "jsr:@denotest/module_graph@1.4.0",
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"remote": {
|
||||||
|
"http://localhost:4545/jsr/registry/@denotest/module_graph/1.4.0/mod.ts": "5b0ce36e08d759118200d8b4627627b5a89b6261fbb0598e6961a6b287abb699",
|
||||||
|
"http://localhost:4545/jsr/registry/@denotest/module_graph/1.4.0/other.ts": "9ce27ca439cb0e218b6e1ec26c043dbc0b54c9babc4cb432df478dd1721faade"
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"dependencies": [
|
||||||
|
"jsr:@denotest/module_graph@1.4"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
// now remove the deps from the deno.json
|
||||||
|
deno_json.write("{}");
|
||||||
|
main_ts.write("");
|
||||||
|
context
|
||||||
|
.new_command()
|
||||||
|
.args("cache main.ts")
|
||||||
|
.run()
|
||||||
|
.skip_output_check();
|
||||||
|
|
||||||
|
lockfile.assert_matches_json(json!({
|
||||||
|
"version": "3",
|
||||||
|
"remote": {}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
itest!(mts_dmts_mjs {
|
itest!(mts_dmts_mjs {
|
||||||
args: "run subdir/import.mts",
|
args: "run subdir/import.mts",
|
||||||
output: "run/mts_dmts_mjs.out",
|
output: "run/mts_dmts_mjs.out",
|
||||||
|
|
3
cli/tests/testdata/npm/lock_file/main.out
vendored
3
cli/tests/testdata/npm/lock_file/main.out
vendored
|
@ -2,6 +2,9 @@ Download [WILDCARD]
|
||||||
error: Integrity check failed for npm package: "@babel/parser@7.19.0". Unable to verify that the package
|
error: Integrity check failed for npm package: "@babel/parser@7.19.0". Unable to verify that the package
|
||||||
is the same as when the lockfile was generated.
|
is the same as when the lockfile was generated.
|
||||||
|
|
||||||
|
Actual: sha512-74bEXKX2h+8rrfQUfsBfuZZHzsEs6Eql4pqy/T4Nn6Y9wNPggQOqD6z6pn5Bl8ZfysKouFZT/UXEH94ummEeQw==
|
||||||
|
Expected: sha512-foobar!
|
||||||
|
|
||||||
This could be caused by:
|
This could be caused by:
|
||||||
* the lock file may be corrupt
|
* the lock file may be corrupt
|
||||||
* the source itself may be corrupt
|
* the source itself may be corrupt
|
||||||
|
|
3
cli/tests/testdata/run/lock_check_ok2.json
vendored
3
cli/tests/testdata/run/lock_check_ok2.json
vendored
|
@ -1,4 +1,6 @@
|
||||||
{
|
{
|
||||||
|
"version": "3",
|
||||||
|
"remote": {
|
||||||
"http://localhost:4545/subdir/mt_application_ecmascript.j2.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
"http://localhost:4545/subdir/mt_application_ecmascript.j2.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
||||||
"http://localhost:4545/subdir/mt_application_x_javascript.j4.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
"http://localhost:4545/subdir/mt_application_x_javascript.j4.js": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
||||||
"http://localhost:4545/subdir/mt_application_x_typescript.t4.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
"http://localhost:4545/subdir/mt_application_x_typescript.t4.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
||||||
|
@ -7,4 +9,5 @@
|
||||||
"http://localhost:4545/subdir/mt_text_typescript.t1.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
"http://localhost:4545/subdir/mt_text_typescript.t1.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
||||||
"http://localhost:4545/subdir/mt_video_mp2t.t3.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
"http://localhost:4545/subdir/mt_video_mp2t.t3.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18",
|
||||||
"http://localhost:4545/subdir/mt_video_vdn.t2.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18"
|
"http://localhost:4545/subdir/mt_video_vdn.t2.ts": "3a3e002e2f92dc8f045bd4a7c66b4791453ad0417b038dd2b2d9d0f277c44f18"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,76 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
use deno_ast::ParsedSource;
|
use deno_ast::ParsedSource;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
use deno_core::serde_json;
|
||||||
use deno_core::ModuleSpecifier;
|
use deno_core::ModuleSpecifier;
|
||||||
use deno_graph::DefaultModuleAnalyzer;
|
use deno_graph::DefaultModuleAnalyzer;
|
||||||
use deno_graph::DependencyDescriptor;
|
use deno_graph::DependencyDescriptor;
|
||||||
use deno_graph::DynamicTemplatePart;
|
use deno_graph::DynamicTemplatePart;
|
||||||
use deno_graph::MediaType;
|
use deno_graph::MediaType;
|
||||||
use deno_graph::TypeScriptReference;
|
use deno_graph::TypeScriptReference;
|
||||||
|
use deno_semver::jsr::JsrDepPackageReq;
|
||||||
|
use deno_semver::jsr::JsrPackageReqReference;
|
||||||
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use import_map::ImportMap;
|
use import_map::ImportMap;
|
||||||
|
|
||||||
use crate::graph_util::format_range_with_colors;
|
use crate::graph_util::format_range_with_colors;
|
||||||
|
|
||||||
|
pub fn import_map_deps(value: &serde_json::Value) -> HashSet<JsrDepPackageReq> {
|
||||||
|
let Some(obj) = value.as_object() else {
|
||||||
|
return Default::default();
|
||||||
|
};
|
||||||
|
let values = imports_values(obj.get("imports"))
|
||||||
|
.into_iter()
|
||||||
|
.chain(scope_values(obj.get("scopes")));
|
||||||
|
values_to_set(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deno_json_deps(
|
||||||
|
config: &deno_config::ConfigFile,
|
||||||
|
) -> HashSet<JsrDepPackageReq> {
|
||||||
|
let values = imports_values(config.json.imports.as_ref())
|
||||||
|
.into_iter()
|
||||||
|
.chain(scope_values(config.json.scopes.as_ref()));
|
||||||
|
values_to_set(values)
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn values_to_set<'a>(
|
||||||
|
values: impl Iterator<Item = &'a String>,
|
||||||
|
) -> HashSet<JsrDepPackageReq> {
|
||||||
|
let mut entries = HashSet::new();
|
||||||
|
for value in values {
|
||||||
|
if let Ok(req_ref) = JsrPackageReqReference::from_str(value) {
|
||||||
|
entries.insert(JsrDepPackageReq::jsr(req_ref.into_inner().req));
|
||||||
|
} else if let Ok(req_ref) = NpmPackageReqReference::from_str(value) {
|
||||||
|
entries.insert(JsrDepPackageReq::npm(req_ref.into_inner().req));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
entries
|
||||||
|
}
|
||||||
|
|
||||||
pub struct ImportMapUnfurler<'a> {
|
pub struct ImportMapUnfurler<'a> {
|
||||||
import_map: &'a ImportMap,
|
import_map: &'a ImportMap,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -218,6 +219,7 @@ impl PathRef {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
pub fn assert_matches_file(&self, wildcard_file: impl AsRef<Path>) -> &Self {
|
pub fn assert_matches_file(&self, wildcard_file: impl AsRef<Path>) -> &Self {
|
||||||
let wildcard_file = testdata_path().join(wildcard_file);
|
let wildcard_file = testdata_path().join(wildcard_file);
|
||||||
println!("output path {}", wildcard_file);
|
println!("output path {}", wildcard_file);
|
||||||
|
@ -225,11 +227,22 @@ impl PathRef {
|
||||||
self.assert_matches_text(&expected_text)
|
self.assert_matches_text(&expected_text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
pub fn assert_matches_text(&self, wildcard_text: impl AsRef<str>) -> &Self {
|
pub fn assert_matches_text(&self, wildcard_text: impl AsRef<str>) -> &Self {
|
||||||
let actual = self.read_to_string();
|
let actual = self.read_to_string();
|
||||||
assert_wildcard_match(&actual, wildcard_text.as_ref());
|
assert_wildcard_match(&actual, wildcard_text.as_ref());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[track_caller]
|
||||||
|
pub fn assert_matches_json(&self, expected: serde_json::Value) {
|
||||||
|
let actual_json = self.read_json_value();
|
||||||
|
if actual_json != expected {
|
||||||
|
let actual_text = serde_json::to_string_pretty(&actual_json).unwrap();
|
||||||
|
let expected_text = serde_json::to_string_pretty(&expected).unwrap();
|
||||||
|
assert_eq!(actual_text, expected_text);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
|
|
Loading…
Reference in a new issue