1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-24 15:19:26 -05:00

feat: infer dependencies from package.json (#22563)

<!--
Before submitting a PR, please read
https://docs.deno.com/runtime/manual/references/contributing

1. Give the PR a descriptive title.

  Examples of good title:
    - fix(std/http): Fix race condition in server
    - docs(console): Update docstrings
    - feat(doc): Handle nested reexports

  Examples of bad title:
    - fix #7123
    - update docs
    - fix bugs

2. Ensure there is a related issue and it is referenced in the PR text.
3. Ensure there are tests that cover the changes.
4. Ensure `cargo test` passes.
5. Ensure `./tools/format.js` passes without changing files.
6. Ensure `./tools/lint.js` passes.
7. Open as a draft PR if your work is still in progress. The CI won't
run
   all steps, but you can add '[ci]' to a commit message to force it to.
8. If you would like to run the benchmarks on the CI, add the 'ci-bench'
label.
-->
This PR enhances the `deno publish` command to infer dependencies from
`package.json` if present.
This commit is contained in:
Marvin Hagemeister 2024-02-23 15:56:49 +01:00 committed by GitHub
parent 55fa61abc6
commit cddefecfff
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 93 additions and 19 deletions

View file

@ -756,12 +756,12 @@ impl Flags {
.ok() .ok()
} }
Task(_) | Check(_) | Coverage(_) | Cache(_) | Info(_) | Eval(_) Task(_) | Check(_) | Coverage(_) | Cache(_) | Info(_) | Eval(_)
| Test(_) | Bench(_) | Repl(_) | Compile(_) => { | Test(_) | Bench(_) | Repl(_) | Compile(_) | Publish(_) => {
std::env::current_dir().ok() std::env::current_dir().ok()
} }
Bundle(_) | Completions(_) | Doc(_) | Fmt(_) | Init(_) | Install(_) Bundle(_) | Completions(_) | Doc(_) | Fmt(_) | Init(_) | Install(_)
| Uninstall(_) | Jupyter(_) | Lsp | Lint(_) | Types | Upgrade(_) | Uninstall(_) | Jupyter(_) | Lsp | Lint(_) | Types | Upgrade(_)
| Vendor(_) | Publish(_) => None, | Vendor(_) => None,
} }
} }

View file

@ -34,6 +34,7 @@ use crate::cache::ParsedSourceCache;
use crate::factory::CliFactory; use crate::factory::CliFactory;
use crate::graph_util::ModuleGraphCreator; use crate::graph_util::ModuleGraphCreator;
use crate::http_util::HttpClient; use crate::http_util::HttpClient;
use crate::resolver::MappedSpecifierResolver;
use crate::tools::check::CheckOptions; use crate::tools::check::CheckOptions;
use crate::tools::lint::no_slow_types; use crate::tools::lint::no_slow_types;
use crate::tools::registry::diagnostics::PublishDiagnostic; use crate::tools::registry::diagnostics::PublishDiagnostic;
@ -85,7 +86,7 @@ async fn prepare_publish(
deno_json: &ConfigFile, deno_json: &ConfigFile,
source_cache: Arc<ParsedSourceCache>, source_cache: Arc<ParsedSourceCache>,
graph: Arc<deno_graph::ModuleGraph>, graph: Arc<deno_graph::ModuleGraph>,
import_map: Arc<ImportMap>, mapped_resolver: Arc<MappedSpecifierResolver>,
diagnostics_collector: &PublishDiagnosticsCollector, diagnostics_collector: &PublishDiagnosticsCollector,
) -> Result<Rc<PreparedPublishPackage>, AnyError> { ) -> Result<Rc<PreparedPublishPackage>, AnyError> {
let config_path = deno_json.specifier.to_file_path().unwrap(); let config_path = deno_json.specifier.to_file_path().unwrap();
@ -131,7 +132,7 @@ async fn prepare_publish(
let diagnostics_collector = diagnostics_collector.clone(); let diagnostics_collector = diagnostics_collector.clone();
let tarball = deno_core::unsync::spawn_blocking(move || { let tarball = deno_core::unsync::spawn_blocking(move || {
let unfurler = ImportMapUnfurler::new(&import_map); let unfurler = ImportMapUnfurler::new(&mapped_resolver);
tar::create_gzipped_tarball( tar::create_gzipped_tarball(
&dir_path, &dir_path,
LazyGraphSourceParser::new(&source_cache, &graph), LazyGraphSourceParser::new(&source_cache, &graph),
@ -654,7 +655,7 @@ async fn prepare_packages_for_publishing(
allow_slow_types: bool, allow_slow_types: bool,
diagnostics_collector: &PublishDiagnosticsCollector, diagnostics_collector: &PublishDiagnosticsCollector,
deno_json: ConfigFile, deno_json: ConfigFile,
import_map: Arc<ImportMap>, mapped_resolver: Arc<MappedSpecifierResolver>,
) -> Result<PreparePackagesData, AnyError> { ) -> Result<PreparePackagesData, AnyError> {
let members = deno_json.to_workspace_members()?; let members = deno_json.to_workspace_members()?;
let module_graph_creator = cli_factory.module_graph_creator().await?.as_ref(); let module_graph_creator = cli_factory.module_graph_creator().await?.as_ref();
@ -684,7 +685,7 @@ async fn prepare_packages_for_publishing(
let results = members let results = members
.into_iter() .into_iter()
.map(|member| { .map(|member| {
let import_map = import_map.clone(); let mapped_resolver = mapped_resolver.clone();
let graph = graph.clone(); let graph = graph.clone();
async move { async move {
let package = prepare_publish( let package = prepare_publish(
@ -692,7 +693,7 @@ async fn prepare_packages_for_publishing(
&member.config_file, &member.config_file,
source_cache.clone(), source_cache.clone(),
graph, graph,
import_map, mapped_resolver,
diagnostics_collector, diagnostics_collector,
) )
.await .await
@ -806,6 +807,11 @@ pub async fn publish(
Arc::new(ImportMap::new(Url::parse("file:///dev/null").unwrap())) Arc::new(ImportMap::new(Url::parse("file:///dev/null").unwrap()))
}); });
let mapped_resolver = Arc::new(MappedSpecifierResolver::new(
Some(import_map),
cli_factory.package_json_deps_provider().clone(),
));
let directory_path = cli_factory.cli_options().initial_cwd(); let directory_path = cli_factory.cli_options().initial_cwd();
let cli_options = cli_factory.cli_options(); let cli_options = cli_factory.cli_options();
@ -823,7 +829,7 @@ pub async fn publish(
publish_flags.allow_slow_types, publish_flags.allow_slow_types,
&diagnostics_collector, &diagnostics_collector,
config_file.clone(), config_file.clone(),
import_map, mapped_resolver,
) )
.await?; .await?;

View file

@ -14,7 +14,8 @@ use deno_graph::TypeScriptReference;
use deno_semver::jsr::JsrDepPackageReq; use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::jsr::JsrPackageReqReference; use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference; use deno_semver::npm::NpmPackageReqReference;
use import_map::ImportMap;
use crate::resolver::MappedSpecifierResolver;
pub fn import_map_deps(value: &serde_json::Value) -> HashSet<JsrDepPackageReq> { pub fn import_map_deps(value: &serde_json::Value) -> HashSet<JsrDepPackageReq> {
let Some(obj) = value.as_object() else { let Some(obj) = value.as_object() else {
@ -95,11 +96,11 @@ impl ImportMapUnfurlDiagnostic {
} }
pub struct ImportMapUnfurler<'a> { pub struct ImportMapUnfurler<'a> {
import_map: &'a ImportMap, import_map: &'a MappedSpecifierResolver,
} }
impl<'a> ImportMapUnfurler<'a> { impl<'a> ImportMapUnfurler<'a> {
pub fn new(import_map: &'a ImportMap) -> Self { pub fn new(import_map: &'a MappedSpecifierResolver) -> Self {
Self { import_map } Self { import_map }
} }
@ -117,10 +118,12 @@ impl<'a> ImportMapUnfurler<'a> {
text_changes: &mut Vec<deno_ast::TextChange>| { text_changes: &mut Vec<deno_ast::TextChange>| {
let resolved = self.import_map.resolve(specifier, url); let resolved = self.import_map.resolve(specifier, url);
if let Ok(resolved) = resolved { if let Ok(resolved) = resolved {
text_changes.push(deno_ast::TextChange { if let Some(resolved) = resolved.into_specifier() {
range: to_range(parsed_source, range), text_changes.push(deno_ast::TextChange {
new_text: make_relative_to(url, &resolved), range: to_range(parsed_source, range),
}); new_text: make_relative_to(url, &resolved),
});
}
} }
}; };
for dep in &module_info.dependencies { for dep in &module_info.dependencies {
@ -206,7 +209,7 @@ fn make_relative_to(from: &ModuleSpecifier, to: &ModuleSpecifier) -> String {
/// Attempts to unfurl the dynamic dependency returning `true` on success /// Attempts to unfurl the dynamic dependency returning `true` on success
/// or `false` when the import was not analyzable. /// or `false` when the import was not analyzable.
fn try_unfurl_dynamic_dep( fn try_unfurl_dynamic_dep(
import_map: &ImportMap, mapped_resolver: &MappedSpecifierResolver,
module_url: &lsp_types::Url, module_url: &lsp_types::Url,
parsed_source: &ParsedSource, parsed_source: &ParsedSource,
dep: &deno_graph::DynamicDependencyDescriptor, dep: &deno_graph::DynamicDependencyDescriptor,
@ -220,10 +223,13 @@ fn try_unfurl_dynamic_dep(
let Some(relative_index) = maybe_relative_index else { let Some(relative_index) = maybe_relative_index else {
return false; return false;
}; };
let resolved = import_map.resolve(value, module_url); let resolved = mapped_resolver.resolve(value, module_url);
let Ok(resolved) = resolved else { let Ok(resolved) = resolved else {
return false; return false;
}; };
let Some(resolved) = resolved.into_specifier() else {
return false;
};
let start = range.start + relative_index; let start = range.start + relative_index;
text_changes.push(deno_ast::TextChange { text_changes.push(deno_ast::TextChange {
range: start..start + value.len(), range: start..start + value.len(),
@ -241,7 +247,10 @@ fn try_unfurl_dynamic_dep(
if !value.ends_with('/') { if !value.ends_with('/') {
return false; return false;
} }
let Ok(resolved) = import_map.resolve(value, module_url) else { let Ok(resolved) = mapped_resolver.resolve(value, module_url) else {
return false;
};
let Some(resolved) = resolved.into_specifier() else {
return false; return false;
}; };
let range = to_range(parsed_source, &dep.argument_range); let range = to_range(parsed_source, &dep.argument_range);
@ -289,6 +298,10 @@ fn to_range(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::sync::Arc;
use crate::args::PackageJsonDepsProvider;
use super::*; use super::*;
use deno_ast::MediaType; use deno_ast::MediaType;
use deno_ast::ModuleSpecifier; use deno_ast::ModuleSpecifier;
@ -323,7 +336,11 @@ mod tests {
}); });
let ImportMapWithDiagnostics { import_map, .. } = let ImportMapWithDiagnostics { import_map, .. } =
import_map::parse_from_value(&deno_json_url, value).unwrap(); import_map::parse_from_value(&deno_json_url, value).unwrap();
let unfurler = ImportMapUnfurler::new(&import_map); let mapped_resolved = MappedSpecifierResolver::new(
Some(Arc::new(import_map)),
Arc::new(PackageJsonDepsProvider::new(None)),
);
let unfurler = ImportMapUnfurler::new(&mapped_resolved);
// Unfurling TS file should apply changes. // Unfurling TS file should apply changes.
{ {

1
test_util/std Submodule

@ -0,0 +1 @@
Subproject commit e0ef24091e87f84d44d495d432d611625b281249

1
test_util/wpt Submodule

@ -0,0 +1 @@
Subproject commit 00f2d3447e634be6beb0261e59e2a3264fa383d6

View file

@ -3,6 +3,7 @@
use deno_core::serde_json::json; use deno_core::serde_json::json;
use test_util::assert_contains; use test_util::assert_contains;
use test_util::assert_not_contains; use test_util::assert_not_contains;
use test_util::env_vars_for_jsr_npm_tests;
use test_util::env_vars_for_jsr_tests; use test_util::env_vars_for_jsr_tests;
use test_util::env_vars_for_npm_tests; use test_util::env_vars_for_npm_tests;
use test_util::itest; use test_util::itest;
@ -147,6 +148,14 @@ itest!(javascript_decl_file {
exit_code: 0, exit_code: 0,
}); });
itest!(package_json {
args: "publish --token 'sadfasdf'",
output: "publish/package_json.out",
cwd: Some("publish/package_json"),
envs: env_vars_for_jsr_npm_tests(),
http_server: true,
});
itest!(successful { itest!(successful {
args: "publish --token 'sadfasdf'", args: "publish --token 'sadfasdf'",
output: "publish/successful.out", output: "publish/successful.out",

View file

@ -0,0 +1,8 @@
Download http://localhost:4545/npm/registry/picocolors
Download http://localhost:4545/npm/registry/picocolors/picocolors-1.0.0.tgz
Check file:///[WILDCARD]/publish/package_json/mod.ts
Checking for slow types in the public API...
Check file:///[WILDCARD]/publish/package_json/mod.ts
Publishing @foo/bar@1.0.0 ...
Successfully published @foo/bar@1.0.0
Visit http://127.0.0.1:4250/@foo/bar@1.0.0 for details

View file

@ -0,0 +1,8 @@
{
"name": "@foo/bar",
"version": "1.0.0",
"exports": {
".": "./mod.ts"
},
"nodeModulesDir": false
}

View file

@ -0,0 +1,9 @@
import pc from "picocolors";
export function add(a: number, b: number): number {
return a + b;
}
export function getValue(): string {
return pc.green("hey");
}

View file

@ -0,0 +1,7 @@
{
"name": "@deno/foo",
"version": "0.0.1",
"dependencies": {
"picocolors": "*"
}
}

View file

@ -64,6 +64,14 @@ pub fn env_vars_for_jsr_tests() -> Vec<(String, String)> {
] ]
} }
pub fn env_vars_for_jsr_npm_tests() -> Vec<(String, String)> {
vec![
("NPM_CONFIG_REGISTRY".to_string(), npm_registry_url()),
("JSR_URL".to_string(), jsr_registry_url()),
("NO_COLOR".to_string(), "1".to_string()),
]
}
pub fn root_path() -> PathRef { pub fn root_path() -> PathRef {
PathRef::new( PathRef::new(
PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR"))) PathBuf::from(concat!(env!("CARGO_MANIFEST_DIR")))