mirror of
https://github.com/denoland/deno.git
synced 2025-03-04 01:44:26 -05:00
feat(unstable/npm): deno info --json
support for npm specifiers (#16472)
This commit is contained in:
parent
c962cd4241
commit
cb08b4683f
8 changed files with 330 additions and 9 deletions
|
@ -733,26 +733,51 @@ itest!(compile_errors {
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(info_chalk {
|
itest!(info_chalk_display {
|
||||||
args: "info --quiet --unstable npm/cjs_with_deps/main.js",
|
args: "info --quiet --unstable npm/cjs_with_deps/main.js",
|
||||||
output: "npm/cjs_with_deps/main.info.out",
|
output: "npm/cjs_with_deps/main_info.out",
|
||||||
exit_code: 0,
|
exit_code: 0,
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(info_chalk_node_modules_dir {
|
itest!(info_chalk_display_node_modules_dir {
|
||||||
args: "info --quiet --unstable --node-modules-dir $TESTDATA/npm/cjs_with_deps/main.js",
|
args: "info --quiet --unstable --node-modules-dir $TESTDATA/npm/cjs_with_deps/main.js",
|
||||||
output: "npm/cjs_with_deps/main.info.out",
|
output: "npm/cjs_with_deps/main_info.out",
|
||||||
exit_code: 0,
|
exit_code: 0,
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
temp_cwd: true,
|
temp_cwd: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
itest!(info_cli_chalk {
|
itest!(info_chalk_json {
|
||||||
|
args: "info --quiet --unstable --json npm/cjs_with_deps/main.js",
|
||||||
|
output: "npm/cjs_with_deps/main_info_json.out",
|
||||||
|
exit_code: 0,
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(info_chalk_json_node_modules_dir {
|
||||||
|
args: "info --quiet --unstable --node-modules-dir --json $TESTDATA/npm/cjs_with_deps/main.js",
|
||||||
|
output: "npm/cjs_with_deps/main_info_json.out",
|
||||||
|
exit_code: 0,
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
temp_cwd: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(info_cli_chalk_display {
|
||||||
args: "info --quiet --unstable npm:chalk@4",
|
args: "info --quiet --unstable npm:chalk@4",
|
||||||
output: "npm/deno_info_chalk.out",
|
output: "npm/info/chalk.out",
|
||||||
|
exit_code: 0,
|
||||||
|
envs: env_vars(),
|
||||||
|
http_server: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
itest!(info_cli_chalk_json {
|
||||||
|
args: "info --quiet --unstable --json npm:chalk@4",
|
||||||
|
output: "npm/info/chalk_json.out",
|
||||||
exit_code: 0,
|
exit_code: 0,
|
||||||
envs: env_vars(),
|
envs: env_vars(),
|
||||||
http_server: true,
|
http_server: true,
|
||||||
|
|
|
@ -159,5 +159,6 @@
|
||||||
"specifier": "file://[WILDCARD]/recursive_imports/common.ts"
|
"specifier": "file://[WILDCARD]/recursive_imports/common.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"redirects": {}
|
"redirects": {},
|
||||||
|
"npmPackages": {}
|
||||||
}
|
}
|
||||||
|
|
3
cli/tests/testdata/info/json_output/main.out
vendored
3
cli/tests/testdata/info/json_output/main.out
vendored
|
@ -86,5 +86,6 @@
|
||||||
"specifier": "file://[WILDCARD]/subdir/subdir2/mod2.ts"
|
"specifier": "file://[WILDCARD]/subdir/subdir2/mod2.ts"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"redirects": {}
|
"redirects": {},
|
||||||
|
"npmPackages": {}
|
||||||
}
|
}
|
||||||
|
|
146
cli/tests/testdata/npm/cjs_with_deps/main_info_json.out
vendored
Normal file
146
cli/tests/testdata/npm/cjs_with_deps/main_info_json.out
vendored
Normal file
|
@ -0,0 +1,146 @@
|
||||||
|
{
|
||||||
|
"roots": [
|
||||||
|
"file://[WILDCARD]/main.js"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
|
"specifier": "npm:chai@4.3",
|
||||||
|
"code": {
|
||||||
|
"specifier": "npm:chai@4.3",
|
||||||
|
"span": {
|
||||||
|
"start": {
|
||||||
|
"line": 1,
|
||||||
|
"character": 23
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 1,
|
||||||
|
"character": 37
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npmPackage": "chai@4.3.6"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"specifier": "npm:chalk@4",
|
||||||
|
"code": {
|
||||||
|
"specifier": "npm:chalk@4",
|
||||||
|
"span": {
|
||||||
|
"start": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 18
|
||||||
|
},
|
||||||
|
"end": {
|
||||||
|
"line": 0,
|
||||||
|
"character": 31
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"npmPackage": "chalk@4.1.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"kind": "esm",
|
||||||
|
"local": "[WILDCARD]main.js",
|
||||||
|
"emit": null,
|
||||||
|
"map": null,
|
||||||
|
"size": 325,
|
||||||
|
"mediaType": "JavaScript",
|
||||||
|
"specifier": "[WILDCARD]/main.js"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"redirects": {},
|
||||||
|
"npmPackages": {
|
||||||
|
"ansi-styles@4.3.0": {
|
||||||
|
"name": "ansi-styles",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"dependencies": [
|
||||||
|
"color-convert@2.0.1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"assertion-error@1.1.0": {
|
||||||
|
"name": "assertion-error",
|
||||||
|
"version": "1.1.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"chai@4.3.6": {
|
||||||
|
"name": "chai",
|
||||||
|
"version": "4.3.6",
|
||||||
|
"dependencies": [
|
||||||
|
"assertion-error@1.1.0",
|
||||||
|
"check-error@1.0.2",
|
||||||
|
"deep-eql@3.0.1",
|
||||||
|
"get-func-name@2.0.0",
|
||||||
|
"loupe@2.3.4",
|
||||||
|
"pathval@1.1.1",
|
||||||
|
"type-detect@4.0.8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chalk@4.1.2": {
|
||||||
|
"name": "chalk",
|
||||||
|
"version": "4.1.2",
|
||||||
|
"dependencies": [
|
||||||
|
"ansi-styles@4.3.0",
|
||||||
|
"supports-color@7.2.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"check-error@1.0.2": {
|
||||||
|
"name": "check-error",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"color-convert@2.0.1": {
|
||||||
|
"name": "color-convert",
|
||||||
|
"version": "2.0.1",
|
||||||
|
"dependencies": [
|
||||||
|
"color-name@1.1.4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"color-name@1.1.4": {
|
||||||
|
"name": "color-name",
|
||||||
|
"version": "1.1.4",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"deep-eql@3.0.1": {
|
||||||
|
"name": "deep-eql",
|
||||||
|
"version": "3.0.1",
|
||||||
|
"dependencies": [
|
||||||
|
"type-detect@4.0.8"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"get-func-name@2.0.0": {
|
||||||
|
"name": "get-func-name",
|
||||||
|
"version": "2.0.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"has-flag@4.0.0": {
|
||||||
|
"name": "has-flag",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"loupe@2.3.4": {
|
||||||
|
"name": "loupe",
|
||||||
|
"version": "2.3.4",
|
||||||
|
"dependencies": [
|
||||||
|
"get-func-name@2.0.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"pathval@1.1.1": {
|
||||||
|
"name": "pathval",
|
||||||
|
"version": "1.1.1",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"supports-color@7.2.0": {
|
||||||
|
"name": "supports-color",
|
||||||
|
"version": "7.2.0",
|
||||||
|
"dependencies": [
|
||||||
|
"has-flag@4.0.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"type-detect@4.0.8": {
|
||||||
|
"name": "type-detect",
|
||||||
|
"version": "4.0.8",
|
||||||
|
"dependencies": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
54
cli/tests/testdata/npm/info/chalk_json.out
vendored
Normal file
54
cli/tests/testdata/npm/info/chalk_json.out
vendored
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
"roots": [
|
||||||
|
"npm:chalk@4"
|
||||||
|
],
|
||||||
|
"modules": [
|
||||||
|
{
|
||||||
|
"kind": "npm",
|
||||||
|
"specifier": "npm:chalk@4",
|
||||||
|
"npmPackage": "chalk@4.1.2"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"redirects": {},
|
||||||
|
"npmPackages": {
|
||||||
|
"ansi-styles@4.3.0": {
|
||||||
|
"name": "ansi-styles",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"dependencies": [
|
||||||
|
"color-convert@2.0.1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"chalk@4.1.2": {
|
||||||
|
"name": "chalk",
|
||||||
|
"version": "4.1.2",
|
||||||
|
"dependencies": [
|
||||||
|
"ansi-styles@4.3.0",
|
||||||
|
"supports-color@7.2.0"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"color-convert@2.0.1": {
|
||||||
|
"name": "color-convert",
|
||||||
|
"version": "2.0.1",
|
||||||
|
"dependencies": [
|
||||||
|
"color-name@1.1.4"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"color-name@1.1.4": {
|
||||||
|
"name": "color-name",
|
||||||
|
"version": "1.1.4",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"has-flag@4.0.0": {
|
||||||
|
"name": "has-flag",
|
||||||
|
"version": "4.0.0",
|
||||||
|
"dependencies": []
|
||||||
|
},
|
||||||
|
"supports-color@7.2.0": {
|
||||||
|
"name": "supports-color",
|
||||||
|
"version": "7.2.0",
|
||||||
|
"dependencies": [
|
||||||
|
"has-flag@4.0.0"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -38,7 +38,9 @@ pub async fn info(flags: Flags, info_flags: InfoFlags) -> Result<(), AnyError> {
|
||||||
let graph = ps.create_graph(vec![(specifier, ModuleKind::Esm)]).await?;
|
let graph = ps.create_graph(vec![(specifier, ModuleKind::Esm)]).await?;
|
||||||
|
|
||||||
if info_flags.json {
|
if info_flags.json {
|
||||||
display::write_json_to_stdout(&json!(graph))?;
|
let mut json_graph = json!(graph);
|
||||||
|
add_npm_packages_to_json(&mut json_graph, &ps.npm_resolver);
|
||||||
|
display::write_json_to_stdout(&json_graph)?;
|
||||||
} else {
|
} else {
|
||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
GraphDisplayContext::write(&graph, &ps.npm_resolver, &mut output)?;
|
GraphDisplayContext::write(&graph, &ps.npm_resolver, &mut output)?;
|
||||||
|
@ -128,6 +130,98 @@ fn print_cache_info(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn add_npm_packages_to_json(
|
||||||
|
json: &mut serde_json::Value,
|
||||||
|
npm_resolver: &NpmPackageResolver,
|
||||||
|
) {
|
||||||
|
// ideally deno_graph could handle this, but for now we just modify the json here
|
||||||
|
let snapshot = npm_resolver.snapshot();
|
||||||
|
let json = json.as_object_mut().unwrap();
|
||||||
|
let modules = json.get_mut("modules").and_then(|m| m.as_array_mut());
|
||||||
|
if let Some(modules) = modules {
|
||||||
|
if modules.len() == 1
|
||||||
|
&& modules[0].get("kind").and_then(|k| k.as_str()) == Some("external")
|
||||||
|
{
|
||||||
|
// If there is only one module and it's "external", then that means
|
||||||
|
// someone provided an npm specifier as a cli argument. In this case,
|
||||||
|
// we want to show which npm package the cli argument resolved to.
|
||||||
|
let module = &mut modules[0];
|
||||||
|
let maybe_package = module
|
||||||
|
.get("specifier")
|
||||||
|
.and_then(|k| k.as_str())
|
||||||
|
.and_then(|specifier| NpmPackageReference::from_str(specifier).ok())
|
||||||
|
.and_then(|package_ref| {
|
||||||
|
snapshot
|
||||||
|
.resolve_package_from_deno_module(&package_ref.req)
|
||||||
|
.ok()
|
||||||
|
});
|
||||||
|
if let Some(pkg) = maybe_package {
|
||||||
|
if let Some(module) = module.as_object_mut() {
|
||||||
|
module.insert("npmPackage".to_string(), format!("{}", pkg.id).into());
|
||||||
|
// change the "kind" to be "npm"
|
||||||
|
module.insert("kind".to_string(), "npm".into());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Filter out npm package references from the modules and instead
|
||||||
|
// have them only listed as dependencies. This is done because various
|
||||||
|
// npm specifiers modules in the graph are really just unresolved
|
||||||
|
// references. So there could be listed multiple npm specifiers
|
||||||
|
// that would resolve to a single npm package.
|
||||||
|
for i in (0..modules.len()).rev() {
|
||||||
|
if modules[i].get("kind").and_then(|k| k.as_str()) == Some("external") {
|
||||||
|
modules.remove(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for module in modules.iter_mut() {
|
||||||
|
let dependencies = module
|
||||||
|
.get_mut("dependencies")
|
||||||
|
.and_then(|d| d.as_array_mut());
|
||||||
|
if let Some(dependencies) = dependencies {
|
||||||
|
for dep in dependencies.iter_mut() {
|
||||||
|
if let serde_json::Value::Object(dep) = dep {
|
||||||
|
let specifier = dep.get("specifier").and_then(|s| s.as_str());
|
||||||
|
if let Some(specifier) = specifier {
|
||||||
|
if let Ok(npm_ref) = NpmPackageReference::from_str(specifier) {
|
||||||
|
if let Ok(pkg) =
|
||||||
|
snapshot.resolve_package_from_deno_module(&npm_ref.req)
|
||||||
|
{
|
||||||
|
dep.insert(
|
||||||
|
"npmPackage".to_string(),
|
||||||
|
format!("{}", pkg.id).into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sorted_packages = snapshot.all_packages();
|
||||||
|
sorted_packages.sort_by(|a, b| a.id.cmp(&b.id));
|
||||||
|
let mut json_packages = serde_json::Map::with_capacity(sorted_packages.len());
|
||||||
|
for pkg in sorted_packages {
|
||||||
|
let mut kv = serde_json::Map::new();
|
||||||
|
kv.insert("name".to_string(), pkg.id.name.to_string().into());
|
||||||
|
kv.insert("version".to_string(), pkg.id.version.to_string().into());
|
||||||
|
let mut deps = pkg.dependencies.values().collect::<Vec<_>>();
|
||||||
|
deps.sort();
|
||||||
|
let deps = deps
|
||||||
|
.into_iter()
|
||||||
|
.map(|id| serde_json::Value::String(format!("{}", id)))
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
kv.insert("dependencies".to_string(), deps.into());
|
||||||
|
|
||||||
|
json_packages.insert(format!("{}", &pkg.id), kv.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
json.insert("npmPackages".to_string(), json_packages.into());
|
||||||
|
}
|
||||||
|
|
||||||
struct TreeNode {
|
struct TreeNode {
|
||||||
text: String,
|
text: String,
|
||||||
children: Vec<TreeNode>,
|
children: Vec<TreeNode>,
|
||||||
|
|
Loading…
Add table
Reference in a new issue