summaryrefslogtreecommitdiff
path: root/cli/tools/registry/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/registry/mod.rs')
-rw-r--r--cli/tools/registry/mod.rs195
1 files changed, 77 insertions, 118 deletions
diff --git a/cli/tools/registry/mod.rs b/cli/tools/registry/mod.rs
index 9205d9b26..586115f27 100644
--- a/cli/tools/registry/mod.rs
+++ b/cli/tools/registry/mod.rs
@@ -8,6 +8,7 @@ use std::sync::Arc;
use base64::prelude::BASE64_STANDARD;
use base64::Engine;
use deno_config::ConfigFile;
+use deno_config::WorkspaceMemberConfig;
use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
@@ -33,12 +34,10 @@ use crate::factory::CliFactory;
use crate::graph_util::ModuleGraphBuilder;
use crate::http_util::HttpClient;
use crate::tools::check::CheckOptions;
+use crate::tools::lint::no_slow_types;
+use crate::tools::registry::diagnostics::PublishDiagnostic;
use crate::tools::registry::diagnostics::PublishDiagnosticsCollector;
-use crate::tools::registry::graph::collect_fast_check_type_graph_diagnostics;
use crate::tools::registry::graph::collect_invalid_external_imports;
-use crate::tools::registry::graph::get_workspace_member_roots;
-use crate::tools::registry::graph::resolve_config_file_roots_from_exports;
-use crate::tools::registry::graph::MemberRoots;
use crate::util::display::human_size;
use crate::util::import_map::ImportMapUnfurler;
@@ -80,16 +79,8 @@ impl PreparedPublishPackage {
static SUGGESTED_ENTRYPOINTS: [&str; 4] =
["mod.ts", "mod.js", "index.ts", "index.js"];
-fn get_deno_json_package_name(
- deno_json: &ConfigFile,
-) -> Result<String, AnyError> {
- match deno_json.json.name.clone() {
- Some(name) => Ok(name),
- None => bail!("{} is missing 'name' field", deno_json.specifier),
- }
-}
-
async fn prepare_publish(
+ package_name: &str,
deno_json: &ConfigFile,
source_cache: Arc<ParsedSourceCache>,
graph: Arc<deno_graph::ModuleGraph>,
@@ -101,7 +92,6 @@ async fn prepare_publish(
let Some(version) = deno_json.json.version.clone() else {
bail!("{} is missing 'version' field", deno_json.specifier);
};
- let name = get_deno_json_package_name(deno_json)?;
if deno_json.json.exports.is_none() {
let mut suggested_entrypoint = None;
@@ -118,22 +108,22 @@ async fn prepare_publish(
"version": "{}",
"exports": "{}"
}}"#,
- name,
+ package_name,
version,
suggested_entrypoint.unwrap_or("<path_to_entrypoint>")
);
bail!(
"You did not specify an entrypoint to \"{}\" package in {}. Add `exports` mapping in the configuration file, eg:\n{}",
- name,
+ package_name,
deno_json.specifier,
exports_content
);
}
- let Some(name) = name.strip_prefix('@') else {
+ let Some(name_no_at) = package_name.strip_prefix('@') else {
bail!("Invalid package name, use '@<scope_name>/<package_name> format");
};
- let Some((scope, package_name)) = name.split_once('/') else {
+ let Some((scope, name_no_scope)) = name_no_at.split_once('/') else {
bail!("Invalid package name, use '@<scope_name>/<package_name> format");
};
let file_patterns = deno_json.to_publish_config()?.map(|c| c.files);
@@ -152,11 +142,11 @@ async fn prepare_publish(
})
.await??;
- log::debug!("Tarball size ({}): {}", name, tarball.bytes.len());
+ log::debug!("Tarball size ({}): {}", package_name, tarball.bytes.len());
Ok(Rc::new(PreparedPublishPackage {
scope: scope.to_string(),
- package: package_name.to_string(),
+ package: name_no_scope.to_string(),
version: version.to_string(),
tarball,
// the config file is always at the root of a publishing dir,
@@ -660,77 +650,44 @@ struct PreparePackagesData {
async fn prepare_packages_for_publishing(
cli_factory: &CliFactory,
- no_zap: bool,
+ allow_slow_types: bool,
diagnostics_collector: &PublishDiagnosticsCollector,
deno_json: ConfigFile,
import_map: Arc<ImportMap>,
) -> Result<PreparePackagesData, AnyError> {
- let maybe_workspace_config = deno_json.to_workspace_config()?;
+ let members = deno_json.to_workspace_members()?;
let module_graph_builder = cli_factory.module_graph_builder().await?.as_ref();
let source_cache = cli_factory.parsed_source_cache();
let type_checker = cli_factory.type_checker().await?;
let cli_options = cli_factory.cli_options();
- let Some(workspace_config) = maybe_workspace_config else {
- let roots = resolve_config_file_roots_from_exports(&deno_json)?;
- let graph = build_and_check_graph_for_publish(
- module_graph_builder,
- type_checker,
- cli_options,
- no_zap,
- diagnostics_collector,
- &[MemberRoots {
- name: get_deno_json_package_name(&deno_json)?,
- dir_url: deno_json.specifier.join("./").unwrap().clone(),
- exports: roots,
- }],
- )
- .await?;
- let package = prepare_publish(
- &deno_json,
- source_cache.clone(),
- graph,
- import_map,
- diagnostics_collector,
- )
- .await?;
- let package_name = format!("@{}/{}", package.scope, package.package);
- let publish_order_graph =
- PublishOrderGraph::new_single(package_name.clone());
- let package_by_name = HashMap::from([(package_name, package)]);
- return Ok(PreparePackagesData {
- publish_order_graph,
- package_by_name,
- });
- };
+ if members.len() > 1 {
+ println!("Publishing a workspace...");
+ }
- println!("Publishing a workspace...");
// create the module graph
- let roots = get_workspace_member_roots(&workspace_config)?;
let graph = build_and_check_graph_for_publish(
module_graph_builder,
type_checker,
cli_options,
- no_zap,
+ allow_slow_types,
diagnostics_collector,
- &roots,
+ &members,
)
.await?;
- let mut package_by_name =
- HashMap::with_capacity(workspace_config.members.len());
+ let mut package_by_name = HashMap::with_capacity(members.len());
let publish_order_graph =
- publish_order::build_publish_order_graph(&graph, &roots)?;
+ publish_order::build_publish_order_graph(&graph, &members)?;
- let results = workspace_config
- .members
- .iter()
- .cloned()
+ let results = members
+ .into_iter()
.map(|member| {
let import_map = import_map.clone();
let graph = graph.clone();
async move {
let package = prepare_publish(
+ &member.package_name,
&member.config_file,
source_cache.clone(),
graph,
@@ -761,64 +718,69 @@ async fn build_and_check_graph_for_publish(
module_graph_builder: &ModuleGraphBuilder,
type_checker: &TypeChecker,
cli_options: &CliOptions,
- no_zap: bool,
+ allow_slow_types: bool,
diagnostics_collector: &PublishDiagnosticsCollector,
- packages: &[MemberRoots],
+ packages: &[WorkspaceMemberConfig],
) -> Result<Arc<deno_graph::ModuleGraph>, deno_core::anyhow::Error> {
- let graph = Arc::new(
- module_graph_builder
- .create_graph_with_options(crate::graph_util::CreateGraphOptions {
- is_dynamic: false,
- // All because we're going to use this same graph to determine the publish order later
- graph_kind: deno_graph::GraphKind::All,
- roots: packages
- .iter()
- .flat_map(|r| r.exports.iter())
- .cloned()
- .collect(),
- workspace_fast_check: true,
- loader: None,
- })
- .await?,
- );
+ let graph =
+ Arc::new(module_graph_builder.create_publish_graph(packages).await?);
graph.valid()?;
+ // todo(dsherret): move to lint rule
collect_invalid_external_imports(&graph, diagnostics_collector);
- let mut has_fast_check_diagnostics = false;
- if !no_zap {
- log::info!("Checking fast check type graph for errors...");
- has_fast_check_diagnostics = collect_fast_check_type_graph_diagnostics(
- &graph,
- packages,
- diagnostics_collector,
+ if allow_slow_types {
+ log::info!(
+ concat!(
+ "{} Publishing a library with slow types is not recommended. ",
+ "This may lead to poor type checking performance for users of ",
+ "your package, may affect the quality of automatic documentation ",
+ "generation, and your package will not be shipped with a .d.ts ",
+ "file for Node.js users."
+ ),
+ colors::yellow("Warning"),
);
- }
+ } else {
+ log::info!("Checking for slow types in the public API...");
+ let mut any_pkg_had_diagnostics = false;
+ for package in packages {
+ let export_urls = package.config_file.resolve_export_value_urls()?;
+ let diagnostics =
+ no_slow_types::collect_no_slow_type_diagnostics(&export_urls, &graph);
+ if !diagnostics.is_empty() {
+ any_pkg_had_diagnostics = true;
+ for diagnostic in diagnostics {
+ diagnostics_collector.push(PublishDiagnostic::FastCheck(diagnostic));
+ }
+ }
+ }
- if !has_fast_check_diagnostics {
- log::info!("Ensuring type checks...");
- let diagnostics = type_checker
- .check_diagnostics(
- graph.clone(),
- CheckOptions {
- lib: cli_options.ts_type_lib_window(),
- log_ignored_options: false,
- reload: cli_options.reload_flag(),
- },
- )
- .await?;
- if !diagnostics.is_empty() {
- bail!(
- concat!(
- "{:#}\n\n",
- "You may have discovered a bug in Deno's fast check implementation. ",
- "Fast check is still early days and we would appreciate if you log a ",
- "bug if you believe this is one: https://github.com/denoland/deno/issues/"
- ),
- diagnostics
- );
+ if !any_pkg_had_diagnostics {
+ // this is a temporary measure until we know that fast check is reliable and stable
+ let check_diagnostics = type_checker
+ .check_diagnostics(
+ graph.clone(),
+ CheckOptions {
+ lib: cli_options.ts_type_lib_window(),
+ log_ignored_options: false,
+ reload: cli_options.reload_flag(),
+ },
+ )
+ .await?;
+ if !check_diagnostics.is_empty() {
+ bail!(
+ concat!(
+ "Failed ensuring public API type output is valid.\n\n",
+ "{:#}\n\n",
+ "You may have discovered a bug in Deno. Please open an issue at: ",
+ "https://github.com/denoland/deno/issues/"
+ ),
+ check_diagnostics
+ );
+ }
}
}
+
Ok(graph)
}
@@ -852,7 +814,7 @@ pub async fn publish(
let prepared_data = prepare_packages_for_publishing(
&cli_factory,
- publish_flags.no_zap,
+ publish_flags.allow_slow_types,
&diagnostics_collector,
config_file.clone(),
import_map,
@@ -866,10 +828,7 @@ pub async fn publish(
}
if publish_flags.dry_run {
- log::warn!(
- "{} Aborting due to --dry-run",
- crate::colors::yellow("Warning")
- );
+ log::warn!("{} Aborting due to --dry-run", colors::yellow("Warning"));
return Ok(());
}