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

feat(publish): support sloppy imports and bare node built-ins (#22588)

This commit is contained in:
Luca Casonato 2024-02-27 16:13:16 +01:00 committed by GitHub
parent 47c2a63d87
commit 8d5c231349
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 316 additions and 130 deletions

View file

@ -44,10 +44,10 @@ use crate::resolver::SloppyImportsResolver;
use crate::standalone::DenoCompileBinaryWriter;
use crate::tools::check::TypeChecker;
use crate::tools::coverage::CoverageCollector;
use crate::tools::registry::deno_json_deps;
use crate::tools::run::hmr::HmrRunner;
use crate::util::file_watcher::WatcherCommunicator;
use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::util::import_map::deno_json_deps;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
use crate::worker::CliMainWorkerFactory;

View file

@ -20,7 +20,7 @@ use deno_core::error::AnyError;
use deno_graph::FastCheckDiagnostic;
use lsp_types::Url;
use crate::util::import_map::ImportMapUnfurlDiagnostic;
use super::unfurl::SpecifierUnfurlerDiagnostic;
#[derive(Clone, Default)]
pub struct PublishDiagnosticsCollector {
@ -74,7 +74,7 @@ impl PublishDiagnosticsCollector {
pub enum PublishDiagnostic {
FastCheck(FastCheckDiagnostic),
ImportMapUnfurl(ImportMapUnfurlDiagnostic),
SpecifierUnfurl(SpecifierUnfurlerDiagnostic),
InvalidPath {
path: PathBuf,
message: String,
@ -102,7 +102,7 @@ impl Diagnostic for PublishDiagnostic {
..
}) => DiagnosticLevel::Warning,
FastCheck(_) => DiagnosticLevel::Error,
ImportMapUnfurl(_) => DiagnosticLevel::Warning,
SpecifierUnfurl(_) => DiagnosticLevel::Warning,
InvalidPath { .. } => DiagnosticLevel::Error,
DuplicatePath { .. } => DiagnosticLevel::Error,
UnsupportedFileType { .. } => DiagnosticLevel::Warning,
@ -114,7 +114,7 @@ impl Diagnostic for PublishDiagnostic {
use PublishDiagnostic::*;
match &self {
FastCheck(diagnostic) => diagnostic.code(),
ImportMapUnfurl(diagnostic) => Cow::Borrowed(diagnostic.code()),
SpecifierUnfurl(diagnostic) => Cow::Borrowed(diagnostic.code()),
InvalidPath { .. } => Cow::Borrowed("invalid-path"),
DuplicatePath { .. } => Cow::Borrowed("case-insensitive-duplicate-path"),
UnsupportedFileType { .. } => Cow::Borrowed("unsupported-file-type"),
@ -126,7 +126,7 @@ impl Diagnostic for PublishDiagnostic {
use PublishDiagnostic::*;
match &self {
FastCheck(diagnostic) => diagnostic.message(),
ImportMapUnfurl(diagnostic) => Cow::Borrowed(diagnostic.message()),
SpecifierUnfurl(diagnostic) => Cow::Borrowed(diagnostic.message()),
InvalidPath { message, .. } => Cow::Borrowed(message.as_str()),
DuplicatePath { .. } => {
Cow::Borrowed("package path is a case insensitive duplicate of another path in the package")
@ -142,8 +142,8 @@ impl Diagnostic for PublishDiagnostic {
use PublishDiagnostic::*;
match &self {
FastCheck(diagnostic) => diagnostic.location(),
ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport {
SpecifierUnfurl(diagnostic) => match diagnostic {
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport {
specifier,
text_info,
range,
@ -180,8 +180,8 @@ impl Diagnostic for PublishDiagnostic {
fn snippet(&self) -> Option<DiagnosticSnippet<'_>> {
match &self {
PublishDiagnostic::FastCheck(diagnostic) => diagnostic.snippet(),
PublishDiagnostic::ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport {
PublishDiagnostic::SpecifierUnfurl(diagnostic) => match diagnostic {
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport {
text_info,
range,
..
@ -227,7 +227,7 @@ impl Diagnostic for PublishDiagnostic {
fn hint(&self) -> Option<Cow<'_, str>> {
match &self {
PublishDiagnostic::FastCheck(diagnostic) => diagnostic.hint(),
PublishDiagnostic::ImportMapUnfurl(_) => None,
PublishDiagnostic::SpecifierUnfurl(_) => None,
PublishDiagnostic::InvalidPath { .. } => Some(
Cow::Borrowed("rename or remove the file, or add it to 'publish.exclude' in the config file"),
),
@ -250,11 +250,11 @@ impl Diagnostic for PublishDiagnostic {
PublishDiagnostic::FastCheck(diagnostic) => {
diagnostic.info()
}
PublishDiagnostic::ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport { .. } => Cow::Borrowed(&[
Cow::Borrowed("after publishing this package, imports from the local import map do not work"),
PublishDiagnostic::SpecifierUnfurl(diagnostic) => match diagnostic {
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => Cow::Borrowed(&[
Cow::Borrowed("after publishing this package, imports from the local import map / package.json do not work"),
Cow::Borrowed("dynamic imports that can not be analyzed at publish time will not be rewritten automatically"),
Cow::Borrowed("make sure the dynamic import is resolvable at runtime without an import map")
Cow::Borrowed("make sure the dynamic import is resolvable at runtime without an import map / package.json")
]),
},
PublishDiagnostic::InvalidPath { .. } => Cow::Borrowed(&[
@ -278,8 +278,8 @@ impl Diagnostic for PublishDiagnostic {
fn docs_url(&self) -> Option<Cow<'_, str>> {
match &self {
PublishDiagnostic::FastCheck(diagnostic) => diagnostic.docs_url(),
PublishDiagnostic::ImportMapUnfurl(diagnostic) => match diagnostic {
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport { .. } => None,
PublishDiagnostic::SpecifierUnfurl(diagnostic) => match diagnostic {
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. } => None,
},
PublishDiagnostic::InvalidPath { .. } => {
Some(Cow::Borrowed("https://jsr.io/go/invalid-path"))

View file

@ -35,13 +35,13 @@ use crate::factory::CliFactory;
use crate::graph_util::ModuleGraphCreator;
use crate::http_util::HttpClient;
use crate::resolver::MappedSpecifierResolver;
use crate::resolver::SloppyImportsResolver;
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_invalid_external_imports;
use crate::util::display::human_size;
use crate::util::import_map::ImportMapUnfurler;
mod api;
mod auth;
@ -50,10 +50,13 @@ mod graph;
mod paths;
mod publish_order;
mod tar;
mod unfurl;
use auth::get_auth_method;
use auth::AuthMethod;
use publish_order::PublishOrderGraph;
pub use unfurl::deno_json_deps;
use unfurl::SpecifierUnfurler;
use super::check::TypeChecker;
@ -81,12 +84,15 @@ impl PreparedPublishPackage {
static SUGGESTED_ENTRYPOINTS: [&str; 4] =
["mod.ts", "mod.js", "index.ts", "index.js"];
#[allow(clippy::too_many_arguments)]
async fn prepare_publish(
package_name: &str,
deno_json: &ConfigFile,
source_cache: Arc<ParsedSourceCache>,
graph: Arc<deno_graph::ModuleGraph>,
mapped_resolver: Arc<MappedSpecifierResolver>,
sloppy_imports_resolver: Option<SloppyImportsResolver>,
bare_node_builtins: bool,
diagnostics_collector: &PublishDiagnosticsCollector,
) -> Result<Rc<PreparedPublishPackage>, AnyError> {
let config_path = deno_json.specifier.to_file_path().unwrap();
@ -132,7 +138,11 @@ async fn prepare_publish(
let diagnostics_collector = diagnostics_collector.clone();
let tarball = deno_core::unsync::spawn_blocking(move || {
let unfurler = ImportMapUnfurler::new(&mapped_resolver);
let unfurler = SpecifierUnfurler::new(
&mapped_resolver,
sloppy_imports_resolver.as_ref(),
bare_node_builtins,
);
tar::create_gzipped_tarball(
&dir_path,
LazyGraphSourceParser::new(&source_cache, &graph),
@ -661,7 +671,9 @@ async fn prepare_packages_for_publishing(
let module_graph_creator = cli_factory.module_graph_creator().await?.as_ref();
let source_cache = cli_factory.parsed_source_cache();
let type_checker = cli_factory.type_checker().await?;
let fs = cli_factory.fs();
let cli_options = cli_factory.cli_options();
let bare_node_builtins = cli_options.unstable_bare_node_builtins();
if members.len() > 1 {
println!("Publishing a workspace...");
@ -686,6 +698,11 @@ async fn prepare_packages_for_publishing(
.into_iter()
.map(|member| {
let mapped_resolver = mapped_resolver.clone();
let sloppy_imports_resolver = if cli_options.unstable_sloppy_imports() {
Some(SloppyImportsResolver::new(fs.clone()))
} else {
None
};
let graph = graph.clone();
async move {
let package = prepare_publish(
@ -694,6 +711,8 @@ async fn prepare_packages_for_publishing(
source_cache.clone(),
graph,
mapped_resolver,
sloppy_imports_resolver,
bare_node_builtins,
diagnostics_collector,
)
.await

View file

@ -18,10 +18,10 @@ use tar::Header;
use crate::cache::LazyGraphSourceParser;
use crate::tools::registry::paths::PackagePath;
use crate::util::import_map::ImportMapUnfurler;
use super::diagnostics::PublishDiagnostic;
use super::diagnostics::PublishDiagnosticsCollector;
use super::unfurl::SpecifierUnfurler;
#[derive(Debug, Clone, PartialEq)]
pub struct PublishableTarballFile {
@ -40,7 +40,7 @@ pub fn create_gzipped_tarball(
dir: &Path,
source_parser: LazyGraphSourceParser,
diagnostics_collector: &PublishDiagnosticsCollector,
unfurler: &ImportMapUnfurler,
unfurler: &SpecifierUnfurler,
file_patterns: Option<FilePatterns>,
) -> Result<PublishableTarball, AnyError> {
let mut tar = TarGzArchive::new();
@ -192,7 +192,7 @@ pub fn create_gzipped_tarball(
fn resolve_content_maybe_unfurling(
path: &Path,
specifier: &Url,
unfurler: &ImportMapUnfurler,
unfurler: &SpecifierUnfurler,
source_parser: LazyGraphSourceParser,
diagnostics_collector: &PublishDiagnosticsCollector,
) -> Result<Vec<u8>, AnyError> {
@ -241,7 +241,7 @@ fn resolve_content_maybe_unfurling(
log::debug!("Unfurling {}", specifier);
let mut reporter = |diagnostic| {
diagnostics_collector.push(PublishDiagnostic::ImportMapUnfurl(diagnostic));
diagnostics_collector.push(PublishDiagnostic::SpecifierUnfurl(diagnostic));
};
let content = unfurler.unfurl(specifier, &parsed_source, &mut reporter);
Ok(content.into_bytes())

View file

@ -11,11 +11,13 @@ use deno_graph::DefaultModuleAnalyzer;
use deno_graph::DependencyDescriptor;
use deno_graph::DynamicTemplatePart;
use deno_graph::TypeScriptReference;
use deno_runtime::deno_node::is_builtin_node_module;
use deno_semver::jsr::JsrDepPackageReq;
use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference;
use crate::resolver::MappedSpecifierResolver;
use crate::resolver::SloppyImportsResolver;
pub fn deno_json_deps(
config: &deno_config::ConfigFile,
@ -61,7 +63,7 @@ fn values_to_set<'a>(
}
#[derive(Debug, Clone)]
pub enum ImportMapUnfurlDiagnostic {
pub enum SpecifierUnfurlerDiagnostic {
UnanalyzableDynamicImport {
specifier: ModuleSpecifier,
text_info: SourceTextInfo,
@ -69,7 +71,7 @@ pub enum ImportMapUnfurlDiagnostic {
},
}
impl ImportMapUnfurlDiagnostic {
impl SpecifierUnfurlerDiagnostic {
pub fn code(&self) -> &'static str {
match self {
Self::UnanalyzableDynamicImport { .. } => "unanalyzable-dynamic-import",
@ -85,20 +87,153 @@ impl ImportMapUnfurlDiagnostic {
}
}
pub struct ImportMapUnfurler<'a> {
import_map: &'a MappedSpecifierResolver,
pub struct SpecifierUnfurler<'a> {
mapped_resolver: &'a MappedSpecifierResolver,
sloppy_imports_resolver: Option<&'a SloppyImportsResolver>,
bare_node_builtins: bool,
}
impl<'a> ImportMapUnfurler<'a> {
pub fn new(import_map: &'a MappedSpecifierResolver) -> Self {
Self { import_map }
impl<'a> SpecifierUnfurler<'a> {
pub fn new(
mapped_resolver: &'a MappedSpecifierResolver,
sloppy_imports_resolver: Option<&'a SloppyImportsResolver>,
bare_node_builtins: bool,
) -> Self {
Self {
mapped_resolver,
sloppy_imports_resolver,
bare_node_builtins,
}
}
fn unfurl_specifier(
&self,
referrer: &ModuleSpecifier,
specifier: &str,
) -> Option<String> {
let resolved =
if let Ok(resolved) = self.mapped_resolver.resolve(specifier, referrer) {
resolved.into_specifier()
} else {
None
};
let resolved = match resolved {
Some(resolved) => resolved,
None if self.bare_node_builtins && is_builtin_node_module(specifier) => {
format!("node:{specifier}").parse().unwrap()
}
None => ModuleSpecifier::options()
.base_url(Some(referrer))
.parse(specifier)
.ok()?,
};
// TODO(lucacasonato): this requires integration in deno_graph first
// let resolved = if let Ok(specifier) =
// NpmPackageReqReference::from_specifier(&resolved)
// {
// if let Some(scope_name) = specifier.req().name.strip_prefix("@jsr/") {
// let (scope, name) = scope_name.split_once("__")?;
// let new_specifier = JsrPackageReqReference::new(PackageReqReference {
// req: PackageReq {
// name: format!("@{scope}/{name}"),
// version_req: specifier.req().version_req.clone(),
// },
// sub_path: specifier.sub_path().map(ToOwned::to_owned),
// })
// .to_string();
// ModuleSpecifier::parse(&new_specifier).unwrap()
// } else {
// resolved
// }
// } else {
// resolved
// };
let resolved =
if let Some(sloppy_imports_resolver) = self.sloppy_imports_resolver {
sloppy_imports_resolver
.resolve(&resolved)
.as_specifier()
.clone()
} else {
resolved
};
relative_url(&resolved, referrer, specifier)
}
/// Attempts to unfurl the dynamic dependency returning `true` on success
/// or `false` when the import was not analyzable.
fn try_unfurl_dynamic_dep(
&self,
module_url: &lsp_types::Url,
parsed_source: &ParsedSource,
dep: &deno_graph::DynamicDependencyDescriptor,
text_changes: &mut Vec<deno_ast::TextChange>,
) -> bool {
match &dep.argument {
deno_graph::DynamicArgument::String(specifier) => {
let range = to_range(parsed_source, &dep.argument_range);
let maybe_relative_index =
parsed_source.text_info().text_str()[range.start..].find(specifier);
let Some(relative_index) = maybe_relative_index else {
return false;
};
let unfurled = self.unfurl_specifier(module_url, specifier);
let Some(unfurled) = unfurled else {
return false;
};
let start = range.start + relative_index;
text_changes.push(deno_ast::TextChange {
range: start..start + specifier.len(),
new_text: unfurled,
});
true
}
deno_graph::DynamicArgument::Template(parts) => match parts.first() {
Some(DynamicTemplatePart::String { value: specifier }) => {
// relative doesn't need to be modified
let is_relative =
specifier.starts_with("./") || specifier.starts_with("../");
if is_relative {
return true;
}
if !specifier.ends_with('/') {
return false;
}
let unfurled = self.unfurl_specifier(module_url, specifier);
let Some(unfurled) = unfurled else {
return false;
};
let range = to_range(parsed_source, &dep.argument_range);
let maybe_relative_index =
parsed_source.text_info().text_str()[range.start..].find(specifier);
let Some(relative_index) = maybe_relative_index else {
return false;
};
let start = range.start + relative_index;
text_changes.push(deno_ast::TextChange {
range: start..start + specifier.len(),
new_text: unfurled,
});
true
}
Some(DynamicTemplatePart::Expr) => {
false // failed analyzing
}
None => {
true // ignore
}
},
deno_graph::DynamicArgument::Expr => {
false // failed analyzing
}
}
}
pub fn unfurl(
&self,
url: &ModuleSpecifier,
parsed_source: &ParsedSource,
diagnostic_reporter: &mut dyn FnMut(ImportMapUnfurlDiagnostic),
diagnostic_reporter: &mut dyn FnMut(SpecifierUnfurlerDiagnostic),
) -> String {
let mut text_changes = Vec::new();
let module_info = DefaultModuleAnalyzer::module_info(parsed_source);
@ -106,14 +241,11 @@ impl<'a> ImportMapUnfurler<'a> {
|specifier: &str,
range: &deno_graph::PositionRange,
text_changes: &mut Vec<deno_ast::TextChange>| {
let resolved = self.import_map.resolve(specifier, url);
if let Ok(resolved) = resolved {
if let Some(resolved) = resolved.into_specifier() {
text_changes.push(deno_ast::TextChange {
range: to_range(parsed_source, range),
new_text: make_relative_to(url, &resolved),
});
}
if let Some(unfurled) = self.unfurl_specifier(url, specifier) {
text_changes.push(deno_ast::TextChange {
range: to_range(parsed_source, range),
new_text: unfurled,
});
}
};
for dep in &module_info.dependencies {
@ -126,8 +258,7 @@ impl<'a> ImportMapUnfurler<'a> {
);
}
DependencyDescriptor::Dynamic(dep) => {
let success = try_unfurl_dynamic_dep(
self.import_map,
let success = self.try_unfurl_dynamic_dep(
url,
parsed_source,
dep,
@ -144,7 +275,7 @@ impl<'a> ImportMapUnfurler<'a> {
.line_start(dep.argument_range.end.line)
+ dep.argument_range.end.character;
diagnostic_reporter(
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport {
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport {
specifier: url.to_owned(),
range: SourceRange::new(start_pos, end_pos),
text_info: parsed_source.text_info().clone(),
@ -188,85 +319,20 @@ impl<'a> ImportMapUnfurler<'a> {
}
}
fn make_relative_to(from: &ModuleSpecifier, to: &ModuleSpecifier) -> String {
if to.scheme() == "file" {
format!("./{}", from.make_relative(to).unwrap())
fn relative_url(
resolved: &ModuleSpecifier,
referrer: &ModuleSpecifier,
specifier: &str,
) -> Option<String> {
let new_specifier = if resolved.scheme() == "file" {
format!("./{}", referrer.make_relative(resolved).unwrap())
} else {
to.to_string()
}
}
/// Attempts to unfurl the dynamic dependency returning `true` on success
/// or `false` when the import was not analyzable.
fn try_unfurl_dynamic_dep(
mapped_resolver: &MappedSpecifierResolver,
module_url: &lsp_types::Url,
parsed_source: &ParsedSource,
dep: &deno_graph::DynamicDependencyDescriptor,
text_changes: &mut Vec<deno_ast::TextChange>,
) -> bool {
match &dep.argument {
deno_graph::DynamicArgument::String(value) => {
let range = to_range(parsed_source, &dep.argument_range);
let maybe_relative_index =
parsed_source.text_info().text_str()[range.start..].find(value);
let Some(relative_index) = maybe_relative_index else {
return false;
};
let resolved = mapped_resolver.resolve(value, module_url);
let Ok(resolved) = resolved else {
return false;
};
let Some(resolved) = resolved.into_specifier() else {
return false;
};
let start = range.start + relative_index;
text_changes.push(deno_ast::TextChange {
range: start..start + value.len(),
new_text: make_relative_to(module_url, &resolved),
});
true
}
deno_graph::DynamicArgument::Template(parts) => match parts.first() {
Some(DynamicTemplatePart::String { value }) => {
// relative doesn't need to be modified
let is_relative = value.starts_with("./") || value.starts_with("../");
if is_relative {
return true;
}
if !value.ends_with('/') {
return false;
}
let Ok(resolved) = mapped_resolver.resolve(value, module_url) else {
return false;
};
let Some(resolved) = resolved.into_specifier() else {
return false;
};
let range = to_range(parsed_source, &dep.argument_range);
let maybe_relative_index =
parsed_source.text_info().text_str()[range.start..].find(value);
let Some(relative_index) = maybe_relative_index else {
return false;
};
let start = range.start + relative_index;
text_changes.push(deno_ast::TextChange {
range: start..start + value.len(),
new_text: make_relative_to(module_url, &resolved),
});
true
}
Some(DynamicTemplatePart::Expr) => {
false // failed analyzing
}
None => {
true // ignore
}
},
deno_graph::DynamicArgument::Expr => {
false // failed analyzing
}
resolved.to_string()
};
if new_specifier == specifier {
return None;
}
Some(new_specifier)
}
fn to_range(
@ -290,6 +356,7 @@ fn to_range(
mod tests {
use std::sync::Arc;
use crate::args::package_json::get_local_package_json_version_reqs;
use crate::args::PackageJsonDepsProvider;
use super::*;
@ -297,8 +364,12 @@ mod tests {
use deno_ast::ModuleSpecifier;
use deno_core::serde_json::json;
use deno_core::url::Url;
use deno_runtime::deno_fs::RealFs;
use deno_runtime::deno_node::PackageJson;
use import_map::ImportMapWithDiagnostics;
use indexmap::IndexMap;
use pretty_assertions::assert_eq;
use test_util::testdata_path;
fn parse_ast(specifier: &Url, source_code: &str) -> ParsedSource {
let media_type = MediaType::from_specifier(specifier);
@ -315,22 +386,38 @@ mod tests {
#[test]
fn test_unfurling() {
let cwd = testdata_path().join("unfurl").to_path_buf();
let deno_json_url =
ModuleSpecifier::parse("file:///dev/deno.json").unwrap();
ModuleSpecifier::from_file_path(cwd.join("deno.json")).unwrap();
let value = json!({
"imports": {
"express": "npm:express@5",
"lib/": "./lib/",
"fizz": "./fizz/mod.ts"
"fizz": "./fizz/mod.ts",
"@std/fs": "npm:@jsr/std__fs@1",
}
});
let ImportMapWithDiagnostics { import_map, .. } =
import_map::parse_from_value(deno_json_url, value).unwrap();
let mapped_resolved = MappedSpecifierResolver::new(
let mut package_json = PackageJson::empty(cwd.join("package.json"));
package_json.dependencies =
Some(IndexMap::from([("chalk".to_string(), "5".to_string())]));
let mapped_resolver = MappedSpecifierResolver::new(
Some(Arc::new(import_map)),
Arc::new(PackageJsonDepsProvider::new(None)),
Arc::new(PackageJsonDepsProvider::new(Some(
get_local_package_json_version_reqs(&package_json),
))),
);
let fs = Arc::new(RealFs);
let sloppy_imports_resolver = SloppyImportsResolver::new(fs);
let unfurler = SpecifierUnfurler::new(
&mapped_resolver,
Some(&sloppy_imports_resolver),
true,
);
let unfurler = ImportMapUnfurler::new(&mapped_resolved);
// Unfurling TS file should apply changes.
{
@ -338,6 +425,16 @@ mod tests {
import foo from "lib/foo.ts";
import bar from "lib/bar.ts";
import fizz from "fizz";
import chalk from "chalk";
import baz from "./baz";
import b from "./b.js";
import b2 from "./b";
import url from "url";
// TODO: unfurl these to jsr
// import "npm:@jsr/std__fs@1/file";
// import "npm:@jsr/std__fs@1";
// import "npm:@jsr/std__fs";
// import "@std/fs";
const test1 = await import("lib/foo.ts");
const test2 = await import(`lib/foo.ts`);
@ -347,7 +444,8 @@ const test4 = await import(`./lib/${expr}`);
const test5 = await import(`lib${expr}`);
const test6 = await import(`${expr}`);
"#;
let specifier = ModuleSpecifier::parse("file:///dev/mod.ts").unwrap();
let specifier =
ModuleSpecifier::from_file_path(cwd.join("mod.ts")).unwrap();
let source = parse_ast(&specifier, source_code);
let mut d = Vec::new();
let mut reporter = |diagnostic| d.push(diagnostic);
@ -356,7 +454,7 @@ const test6 = await import(`${expr}`);
assert!(
matches!(
d[0],
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport { .. }
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. }
),
"{:?}",
d[0]
@ -364,7 +462,7 @@ const test6 = await import(`${expr}`);
assert!(
matches!(
d[1],
ImportMapUnfurlDiagnostic::UnanalyzableDynamicImport { .. }
SpecifierUnfurlerDiagnostic::UnanalyzableDynamicImport { .. }
),
"{:?}",
d[1]
@ -373,6 +471,16 @@ const test6 = await import(`${expr}`);
import foo from "./lib/foo.ts";
import bar from "./lib/bar.ts";
import fizz from "./fizz/mod.ts";
import chalk from "npm:chalk@5";
import baz from "./baz/index.js";
import b from "./b.ts";
import b2 from "./b.ts";
import url from "node:url";
// TODO: unfurl these to jsr
// import "npm:@jsr/std__fs@1/file";
// import "npm:@jsr/std__fs@1";
// import "npm:@jsr/std__fs";
// import "@std/fs";
const test1 = await import("./lib/foo.ts");
const test2 = await import(`./lib/foo.ts`);

View file

@ -8,7 +8,6 @@ pub mod display;
pub mod draw_thread;
pub mod file_watcher;
pub mod fs;
pub mod import_map;
pub mod logger;
pub mod path;
pub mod progress_bar;

View file

@ -224,6 +224,22 @@ itest!(config_flag {
http_server: true,
});
itest!(bare_node_builtins {
args: "publish --token 'sadfasdf' --dry-run --unstable-bare-node-builtins",
output: "publish/bare_node_builtins.out",
cwd: Some("publish/bare_node_builtins"),
envs: env_vars_for_jsr_npm_tests(),
http_server: true,
});
itest!(sloppy_imports {
args: "publish --token 'sadfasdf' --dry-run --unstable-sloppy-imports",
output: "publish/sloppy_imports.out",
cwd: Some("publish/sloppy_imports"),
envs: env_vars_for_jsr_tests(),
http_server: true,
});
itest!(jsr_jsonc {
args: "publish --token 'sadfasdf'",
cwd: Some("publish/jsr_jsonc"),

View file

@ -0,0 +1,11 @@
Warning: Resolving "url" as "node:url" at file:///[WILDCARD]/publish/bare_node_builtins/mod.ts:1:22. If you want to use a built-in Node module, add a "node:" prefix.
Warning: Resolving "url" as "node:url" at file:///[WILDCARD]/publish/bare_node_builtins/mod.ts:1:22. If you want to use a built-in Node module, add a "node:" prefix.
Download http://localhost:4545/npm/registry/@types/node
Download http://localhost:4545/npm/registry/@types/node/node-18.8.2.tgz
Check file:///[WILDCARD]/publish/bare_node_builtins/mod.ts
Checking for slow types in the public API...
Check file:///[WILDCARD]/publish/bare_node_builtins/mod.ts
Simulating publish of @foo/bar@1.0.0 with files:
file:///[WILDCARD]/publish/bare_node_builtins/deno.json (87B)
file:///[WILDCARD]/publish/bare_node_builtins/mod.ts (121B)
Warning Aborting due to --dry-run

View file

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

View file

@ -0,0 +1,5 @@
import * as url from "url";
export function foobar(): { href: string } {
return url.pathToFileURL("/foo/bar");
}

View file

@ -0,0 +1,12 @@
Warning Sloppy module resolution (hint: specify path to index.ts file in directory instead)
at file:///[WILDCARD]/publish/sloppy_imports/mod.ts:1:20
Warning Sloppy module resolution (hint: specify path to index.ts file in directory instead)
at file:///[WILDCARD]/publish/sloppy_imports/mod.ts:1:20
Check file:///[WILDCARD]/publish/sloppy_imports/mod.ts
Checking for slow types in the public API...
Check file:///[WILDCARD]/publish/sloppy_imports/mod.ts
Simulating publish of @foo/bar@1.0.0 with files:
file:///[WILDCARD]/publish/sloppy_imports/b/index.ts (27B)
file:///[WILDCARD]/publish/sloppy_imports/deno.json (87B)
file:///[WILDCARD]/publish/sloppy_imports/mod.ts (35B)
Warning Aborting due to --dry-run

View file

@ -0,0 +1 @@
export const PI = Math.PI;

View file

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

View file

@ -0,0 +1 @@
export { PI } from "./b";

View file

@ -7,9 +7,9 @@ warning[unanalyzable-dynamic-import]: unable to analyze dynamic import
2 | await import("asd " + asd);
| ^^^^^^^^^^^^ the unanalyzable dynamic import
info: after publishing this package, imports from the local import map do not work
info: after publishing this package, imports from the local import map / package.json do not work
info: dynamic imports that can not be analyzed at publish time will not be rewritten automatically
info: make sure the dynamic import is resolvable at runtime without an import map
info: make sure the dynamic import is resolvable at runtime without an import map / package.json
Publishing @foo/bar@1.0.0 ...
Successfully published @foo/bar@1.0.0

0
tests/testdata/unfurl/b.ts vendored Normal file
View file

0
tests/testdata/unfurl/baz/index.js vendored Normal file
View file