summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAsher Gomez <ashersaupingomez@gmail.com>2024-09-03 17:00:57 +1000
committerGitHub <noreply@github.com>2024-09-03 17:00:57 +1000
commit5f08d634f73fab21c17cc02f3f3bf8e8b531eee8 (patch)
treee105697d4ecb23cad491a04af878bc44edfa66a1
parent2533d68cabb5a38be891a9807c452ca802401d46 (diff)
BREAKING: remove `deno vendor` (#25343)
-rw-r--r--cli/args/flags.rs128
-rw-r--r--cli/args/mod.rs20
-rw-r--r--cli/main.rs4
-rw-r--r--cli/tools/mod.rs1
-rw-r--r--cli/tools/vendor/analyze.rs113
-rw-r--r--cli/tools/vendor/build.rs1330
-rw-r--r--cli/tools/vendor/import_map.rs508
-rw-r--r--cli/tools/vendor/mappings.rs255
-rw-r--r--cli/tools/vendor/mod.rs578
-rw-r--r--cli/tools/vendor/specifiers.rs208
-rw-r--r--cli/tools/vendor/test.rs357
-rw-r--r--cli/util/fs.rs41
-rw-r--r--cli/util/path.rs68
-rw-r--r--tests/integration/mod.rs2
-rw-r--r--tests/integration/vendor_tests.rs751
-rw-r--r--tests/specs/vendor/removed/__test__.jsonc13
-rw-r--r--tests/specs/vendor/removed/vendor.out3
-rw-r--r--tests/specs/vendor/removed/vendor_help.out10
-rw-r--r--tests/testdata/vendor/dynamic.ts3
-rw-r--r--tests/testdata/vendor/dynamic_non_analyzable.ts4
-rw-r--r--tests/testdata/vendor/dynamic_non_existent.ts11
-rw-r--r--tests/testdata/vendor/dynamic_non_existent.ts.out9
-rw-r--r--tests/testdata/vendor/logger.ts5
-rw-r--r--tests/testdata/vendor/mod.ts1
-rw-r--r--tests/testdata/vendor/npm_and_node_specifier.ts2
-rw-r--r--tests/testdata/vendor/query_reexport.ts1
26 files changed, 33 insertions, 4393 deletions
diff --git a/cli/args/flags.rs b/cli/args/flags.rs
index 9e50ccc49..5470be976 100644
--- a/cli/args/flags.rs
+++ b/cli/args/flags.rs
@@ -413,13 +413,6 @@ pub struct UpgradeFlags {
}
#[derive(Clone, Debug, Eq, PartialEq)]
-pub struct VendorFlags {
- pub specifiers: Vec<String>,
- pub output_path: Option<String>,
- pub force: bool,
-}
-
-#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PublishFlags {
pub token: Option<String>,
pub dry_run: bool,
@@ -463,7 +456,7 @@ pub enum DenoSubcommand {
Test(TestFlags),
Types,
Upgrade(UpgradeFlags),
- Vendor(VendorFlags),
+ Vendor,
Publish(PublishFlags),
Help(HelpFlags),
}
@@ -3008,58 +3001,14 @@ update to a different location, use the --output flag:
})
}
-// TODO(bartlomieju): this subcommand is now deprecated, remove it in Deno 2.
fn vendor_subcommand() -> Command {
command("vendor",
- "⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.
-Add `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead.
-
-Vendor remote modules into a local directory.
+ "⚠️ `deno vendor` was removed in Deno 2.
-Analyzes the provided modules along with their dependencies, downloads
-remote modules to the output directory, and produces an import map that
-maps remote specifiers to the downloaded files.
- deno vendor main.ts
- deno run --import-map vendor/import_map.json main.ts
-
-Remote modules and multiple modules may also be specified:
- deno vendor main.ts test.deps.ts jsr:@std/path",
+See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations",
UnstableArgsConfig::ResolutionOnly
)
.hide(true)
- .defer(|cmd| cmd
- .arg(
- Arg::new("specifiers")
- .num_args(1..)
- .action(ArgAction::Append)
- .required_unless_present("help"),
- )
- .arg(
- Arg::new("output")
- .long("output")
- .help("The directory to output the vendored modules to")
- .value_parser(value_parser!(String))
- .value_hint(ValueHint::DirPath),
- )
- .arg(
- Arg::new("force")
- .long("force")
- .short('f')
- .help(
- "Forcefully overwrite conflicting files in existing output directory",
- )
- .action(ArgAction::SetTrue),
- )
- .arg(no_config_arg())
- .arg(config_arg())
- .arg(import_map_arg())
- .arg(lock_arg())
- .arg(node_modules_dir_arg())
- .arg(vendor_arg())
- .arg(reload_arg())
- .arg(ca_file_arg())
- .arg(unsafely_ignore_certificate_errors_arg())
- )
}
fn publish_subcommand() -> Command {
@@ -4751,24 +4700,8 @@ fn upgrade_parse(flags: &mut Flags, matches: &mut ArgMatches) {
});
}
-fn vendor_parse(flags: &mut Flags, matches: &mut ArgMatches) {
- unstable_args_parse(flags, matches, UnstableArgsConfig::ResolutionOnly);
- ca_file_arg_parse(flags, matches);
- unsafely_ignore_certificate_errors_parse(flags, matches);
- config_args_parse(flags, matches);
- import_map_arg_parse(flags, matches);
- lock_arg_parse(flags, matches);
- node_modules_and_vendor_dir_arg_parse(flags, matches);
- reload_arg_parse(flags, matches);
-
- flags.subcommand = DenoSubcommand::Vendor(VendorFlags {
- specifiers: matches
- .remove_many::<String>("specifiers")
- .map(|p| p.collect())
- .unwrap_or_default(),
- output_path: matches.remove_one::<String>("output"),
- force: matches.get_flag("force"),
- });
+fn vendor_parse(flags: &mut Flags, _matches: &mut ArgMatches) {
+ flags.subcommand = DenoSubcommand::Vendor
}
fn publish_parse(flags: &mut Flags, matches: &mut ArgMatches) {
@@ -9672,57 +9605,6 @@ mod tests {
}
#[test]
- fn vendor_minimal() {
- let r = flags_from_vec(svec!["deno", "vendor", "mod.ts",]);
- assert_eq!(
- r.unwrap(),
- Flags {
- subcommand: DenoSubcommand::Vendor(VendorFlags {
- specifiers: svec!["mod.ts"],
- force: false,
- output_path: None,
- }),
- ..Flags::default()
- }
- );
- }
-
- #[test]
- fn vendor_all() {
- let r = flags_from_vec(svec![
- "deno",
- "vendor",
- "--config",
- "deno.json",
- "--import-map",
- "import_map.json",
- "--lock",
- "lock.json",
- "--force",
- "--output",
- "out_dir",
- "--reload",
- "mod.ts",
- "deps.test.ts",
- ]);
- assert_eq!(
- r.unwrap(),
- Flags {
- subcommand: DenoSubcommand::Vendor(VendorFlags {
- specifiers: svec!["mod.ts", "deps.test.ts"],
- force: true,
- output_path: Some(String::from("out_dir")),
- }),
- config_flag: ConfigFlag::Path("deno.json".to_owned()),
- import_map_path: Some("import_map.json".to_string()),
- lock: Some(String::from("lock.json")),
- reload: true,
- ..Flags::default()
- }
- );
- }
-
- #[test]
fn task_subcommand() {
let r = flags_from_vec(svec!["deno", "task", "build", "hello", "world",]);
assert_eq!(
diff --git a/cli/args/mod.rs b/cli/args/mod.rs
index 50132b1fb..9be115d5c 100644
--- a/cli/args/mod.rs
+++ b/cli/args/mod.rs
@@ -1217,11 +1217,6 @@ impl CliOptions {
NPM_PROCESS_STATE.is_some()
}
- /// Overrides the import map specifier to use.
- pub fn set_import_map_specifier(&mut self, path: Option<ModuleSpecifier>) {
- self.overrides.import_map_specifier = Some(path);
- }
-
pub fn has_node_modules_dir(&self) -> bool {
self.maybe_node_modules_folder.is_some()
}
@@ -1230,21 +1225,6 @@ impl CliOptions {
self.maybe_node_modules_folder.as_ref()
}
- pub fn with_node_modules_dir_path(&self, path: PathBuf) -> Self {
- Self {
- flags: self.flags.clone(),
- initial_cwd: self.initial_cwd.clone(),
- maybe_node_modules_folder: Some(path),
- npmrc: self.npmrc.clone(),
- maybe_lockfile: self.maybe_lockfile.clone(),
- start_dir: self.start_dir.clone(),
- overrides: self.overrides.clone(),
- disable_deprecated_api_warning: self.disable_deprecated_api_warning,
- verbose_deprecated_api_warning: self.verbose_deprecated_api_warning,
- deno_dir_provider: self.deno_dir_provider.clone(),
- }
- }
-
pub fn node_modules_dir(
&self,
) -> Result<Option<NodeModulesDirMode>, AnyError> {
diff --git a/cli/main.rs b/cli/main.rs
index 33ccc198c..c963cb21c 100644
--- a/cli/main.rs
+++ b/cli/main.rs
@@ -283,9 +283,7 @@ async fn run_subcommand(flags: Arc<Flags>) -> Result<i32, AnyError> {
"This deno was built without the \"upgrade\" feature. Please upgrade using the installation method originally used to install Deno.",
1,
),
- DenoSubcommand::Vendor(vendor_flags) => spawn_subcommand(async {
- tools::vendor::vendor(flags, vendor_flags).await
- }),
+ DenoSubcommand::Vendor => exit_with_message("⚠️ `deno vendor` was removed in Deno 2.\n\nSee the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations", 1),
DenoSubcommand::Publish(publish_flags) => spawn_subcommand(async {
tools::registry::publish(flags, publish_flags).await
}),
diff --git a/cli/tools/mod.rs b/cli/tools/mod.rs
index 0b720e2ac..a458da9f1 100644
--- a/cli/tools/mod.rs
+++ b/cli/tools/mod.rs
@@ -19,4 +19,3 @@ pub mod serve;
pub mod task;
pub mod test;
pub mod upgrade;
-pub mod vendor;
diff --git a/cli/tools/vendor/analyze.rs b/cli/tools/vendor/analyze.rs
deleted file mode 100644
index 3e5964be6..000000000
--- a/cli/tools/vendor/analyze.rs
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use deno_ast::swc::ast::ExportDefaultDecl;
-use deno_ast::swc::ast::ExportSpecifier;
-use deno_ast::swc::ast::ModuleExportName;
-use deno_ast::swc::ast::NamedExport;
-use deno_ast::swc::ast::Program;
-use deno_ast::swc::visit::noop_visit_type;
-use deno_ast::swc::visit::Visit;
-use deno_ast::swc::visit::VisitWith;
-use deno_ast::ParsedSource;
-
-/// Gets if the parsed source has a default export.
-pub fn has_default_export(source: &ParsedSource) -> bool {
- let mut visitor = DefaultExportFinder {
- has_default_export: false,
- };
- let program = source.program();
- let program: &Program = &program;
- program.visit_with(&mut visitor);
- visitor.has_default_export
-}
-
-struct DefaultExportFinder {
- has_default_export: bool,
-}
-
-impl Visit for DefaultExportFinder {
- noop_visit_type!();
-
- fn visit_export_default_decl(&mut self, _: &ExportDefaultDecl) {
- self.has_default_export = true;
- }
-
- fn visit_named_export(&mut self, named_export: &NamedExport) {
- if named_export
- .specifiers
- .iter()
- .any(export_specifier_has_default)
- {
- self.has_default_export = true;
- }
- }
-}
-
-fn export_specifier_has_default(s: &ExportSpecifier) -> bool {
- match s {
- ExportSpecifier::Default(_) => true,
- ExportSpecifier::Namespace(_) => false,
- ExportSpecifier::Named(named) => {
- let export_name = named.exported.as_ref().unwrap_or(&named.orig);
-
- match export_name {
- ModuleExportName::Str(_) => false,
- ModuleExportName::Ident(ident) => &*ident.sym == "default",
- }
- }
- }
-}
-
-#[cfg(test)]
-mod test {
- use deno_ast::MediaType;
- use deno_ast::ModuleSpecifier;
- use deno_ast::ParseParams;
- use deno_ast::ParsedSource;
-
- use super::has_default_export;
-
- #[test]
- fn has_default_when_export_default_decl() {
- let parsed_source = parse_module("export default class Class {}");
- assert!(has_default_export(&parsed_source));
- }
-
- #[test]
- fn has_default_when_named_export() {
- let parsed_source = parse_module("export {default} from './test.ts';");
- assert!(has_default_export(&parsed_source));
- }
-
- #[test]
- fn has_default_when_named_export_alias() {
- let parsed_source =
- parse_module("export {test as default} from './test.ts';");
- assert!(has_default_export(&parsed_source));
- }
-
- #[test]
- fn not_has_default_when_named_export_not_exported() {
- let parsed_source =
- parse_module("export {default as test} from './test.ts';");
- assert!(!has_default_export(&parsed_source));
- }
-
- #[test]
- fn not_has_default_when_not() {
- let parsed_source = parse_module("export {test} from './test.ts'; export class Test{} export * from './test';");
- assert!(!has_default_export(&parsed_source));
- }
-
- fn parse_module(text: &str) -> ParsedSource {
- deno_ast::parse_module(ParseParams {
- specifier: ModuleSpecifier::parse("file:///mod.ts").unwrap(),
- capture_tokens: false,
- maybe_syntax: None,
- media_type: MediaType::TypeScript,
- scope_analysis: false,
- text: text.into(),
- })
- .unwrap()
- }
-}
diff --git a/cli/tools/vendor/build.rs b/cli/tools/vendor/build.rs
deleted file mode 100644
index a4424e3f3..000000000
--- a/cli/tools/vendor/build.rs
+++ /dev/null
@@ -1,1330 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use std::fmt::Write as _;
-use std::path::Path;
-use std::sync::Arc;
-
-use deno_ast::ModuleSpecifier;
-use deno_core::anyhow::bail;
-use deno_core::anyhow::Context;
-use deno_core::error::AnyError;
-use deno_core::futures::future::LocalBoxFuture;
-use deno_graph::source::ResolutionMode;
-use deno_graph::JsModule;
-use deno_graph::Module;
-use deno_graph::ModuleGraph;
-use deno_runtime::deno_fs;
-use import_map::ImportMap;
-use import_map::SpecifierMap;
-
-use crate::args::JsxImportSourceConfig;
-use crate::cache::ParsedSourceCache;
-use crate::graph_util;
-use crate::tools::vendor::import_map::BuildImportMapInput;
-
-use super::analyze::has_default_export;
-use super::import_map::build_import_map;
-use super::mappings::Mappings;
-use super::mappings::ProxiedModule;
-use super::specifiers::is_remote_specifier;
-
-/// Allows substituting the environment for testing purposes.
-pub trait VendorEnvironment {
- fn create_dir_all(&self, dir_path: &Path) -> Result<(), AnyError>;
- fn write_file(&self, file_path: &Path, bytes: &[u8]) -> Result<(), AnyError>;
-}
-
-pub struct RealVendorEnvironment;
-
-impl VendorEnvironment for RealVendorEnvironment {
- fn create_dir_all(&self, dir_path: &Path) -> Result<(), AnyError> {
- Ok(std::fs::create_dir_all(dir_path)?)
- }
-
- fn write_file(&self, file_path: &Path, bytes: &[u8]) -> Result<(), AnyError> {
- std::fs::write(file_path, bytes)
- .with_context(|| format!("Failed writing {}", file_path.display()))
- }
-}
-
-type BuildGraphFuture = LocalBoxFuture<'static, Result<ModuleGraph, AnyError>>;
-
-pub struct BuildInput<
- 'a,
- TBuildGraphFn: FnOnce(Vec<ModuleSpecifier>) -> BuildGraphFuture,
- TEnvironment: VendorEnvironment,
-> {
- pub entry_points: Vec<ModuleSpecifier>,
- pub build_graph: TBuildGraphFn,
- pub parsed_source_cache: &'a ParsedSourceCache,
- pub output_dir: &'a Path,
- pub maybe_original_import_map: Option<&'a ImportMap>,
- pub maybe_jsx_import_source: Option<&'a JsxImportSourceConfig>,
- pub resolver: &'a dyn deno_graph::source::Resolver,
- pub environment: &'a TEnvironment,
-}
-
-pub struct BuildOutput {
- pub vendored_count: usize,
- pub graph: ModuleGraph,
-}
-
-/// Vendors remote modules and returns how many were vendored.
-pub async fn build<
- TBuildGraphFn: FnOnce(Vec<ModuleSpecifier>) -> BuildGraphFuture,
- TEnvironment: VendorEnvironment,
->(
- input: BuildInput<'_, TBuildGraphFn, TEnvironment>,
-) -> Result<BuildOutput, AnyError> {
- let BuildInput {
- mut entry_points,
- build_graph,
- parsed_source_cache,
- output_dir,
- maybe_original_import_map,
- maybe_jsx_import_source,
- resolver,
- environment,
- } = input;
- assert!(output_dir.is_absolute());
- let output_dir_specifier =
- ModuleSpecifier::from_directory_path(output_dir).unwrap();
-
- if let Some(original_im) = &maybe_original_import_map {
- validate_original_import_map(original_im, &output_dir_specifier)?;
- }
-
- // add the jsx import source to the entry points to ensure it is always vendored
- if let Some(jsx_import_source) = maybe_jsx_import_source {
- if let Some(specifier_text) = jsx_import_source.maybe_specifier_text() {
- if let Ok(specifier) = resolver.resolve(
- &specifier_text,
- &deno_graph::Range {
- specifier: jsx_import_source.base_url.clone(),
- start: deno_graph::Position::zeroed(),
- end: deno_graph::Position::zeroed(),
- },
- ResolutionMode::Execution,
- ) {
- entry_points.push(specifier);
- }
- }
- }
-
- let graph = build_graph(entry_points).await?;
-
- // surface any errors
- let real_fs = Arc::new(deno_fs::RealFs) as Arc<dyn deno_fs::FileSystem>;
- graph_util::graph_valid(
- &graph,
- &real_fs,
- &graph.roots.iter().cloned().collect::<Vec<_>>(),
- graph_util::GraphValidOptions {
- is_vendoring: true,
- check_js: true,
- follow_type_only: true,
- exit_lockfile_errors: true,
- },
- )?;
-
- // figure out how to map remote modules to local
- let all_modules = graph.modules().collect::<Vec<_>>();
- let remote_modules = all_modules
- .iter()
- .filter(|m| is_remote_specifier(m.specifier()))
- .copied()
- .collect::<Vec<_>>();
- let mappings =
- Mappings::from_remote_modules(&graph, &remote_modules, output_dir)?;
-
- // write out all the files
- for module in &remote_modules {
- let source = match module {
- Module::Js(module) => &module.source,
- Module::Json(module) => &module.source,
- Module::Node(_) | Module::Npm(_) | Module::External(_) => continue,
- };
- let specifier = module.specifier();
- let local_path = mappings
- .proxied_path(specifier)
- .unwrap_or_else(|| mappings.local_path(specifier));
-
- environment.create_dir_all(local_path.parent().unwrap())?;
- environment.write_file(&local_path, source.as_bytes())?;
- }
-
- // write out the proxies
- for (specifier, proxied_module) in mappings.proxied_modules() {
- let proxy_path = mappings.local_path(specifier);
- let module = graph.get(specifier).unwrap().js().unwrap();
- let text =
- build_proxy_module_source(module, proxied_module, parsed_source_cache)?;
-
- environment.write_file(&proxy_path, text.as_bytes())?;
- }
-
- // create the import map if necessary
- if !remote_modules.is_empty() {
- let import_map_path = output_dir.join("import_map.json");
- let import_map_text = build_import_map(BuildImportMapInput {
- base_dir: &output_dir_specifier,
- graph: &graph,
- modules: &all_modules,
- mappings: &mappings,
- maybe_original_import_map,
- maybe_jsx_import_source,
- resolver,
- parsed_source_cache,
- })?;
- environment.write_file(&import_map_path, import_map_text.as_bytes())?;
- }
-
- Ok(BuildOutput {
- vendored_count: remote_modules.len(),
- graph,
- })
-}
-
-fn validate_original_import_map(
- import_map: &ImportMap,
- output_dir: &ModuleSpecifier,
-) -> Result<(), AnyError> {
- fn validate_imports(
- imports: &SpecifierMap,
- output_dir: &ModuleSpecifier,
- ) -> Result<(), AnyError> {
- for entry in imports.entries() {
- if let Some(value) = entry.value {
- if value.as_str().starts_with(output_dir.as_str()) {
- bail!(
- "Providing an existing import map with entries for the output directory is not supported (\"{}\": \"{}\").",
- entry.raw_key,
- entry.raw_value.unwrap_or("<INVALID>"),
- );
- }
- }
- }
- Ok(())
- }
-
- validate_imports(import_map.imports(), output_dir)?;
-
- for scope in import_map.scopes() {
- if scope.key.starts_with(output_dir.as_str()) {
- bail!(
- "Providing an existing import map with a scope for the output directory is not supported (\"{}\").",
- scope.raw_key,
- );
- }
- validate_imports(scope.imports, output_dir)?;
- }
-
- Ok(())
-}
-
-fn build_proxy_module_source(
- module: &JsModule,
- proxied_module: &ProxiedModule,
- parsed_source_cache: &ParsedSourceCache,
-) -> Result<String, AnyError> {
- let mut text = String::new();
- writeln!(
- text,
- "// @deno-types=\"{}\"",
- proxied_module.declaration_specifier
- )
- .unwrap();
-
- let relative_specifier = format!(
- "./{}",
- proxied_module
- .output_path
- .file_name()
- .unwrap()
- .to_string_lossy()
- );
-
- // for simplicity, always include the `export *` statement as it won't error
- // even when the module does not contain a named export
- writeln!(text, "export * from \"{relative_specifier}\";").unwrap();
-
- // add a default export if one exists in the module
- let parsed_source =
- parsed_source_cache.get_parsed_source_from_js_module(module)?;
- if has_default_export(&parsed_source) {
- writeln!(text, "export {{ default }} from \"{relative_specifier}\";")
- .unwrap();
- }
-
- Ok(text)
-}
-
-#[cfg(test)]
-mod test {
- use crate::args::JsxImportSourceConfig;
- use crate::tools::vendor::test::VendorTestBuilder;
- use deno_core::serde_json::json;
- use pretty_assertions::assert_eq;
-
- #[tokio::test]
- async fn no_remote_modules() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(output.import_map, None,);
- assert_eq!(output.files, vec![],);
- }
-
- #[tokio::test]
- async fn local_specifiers_to_remote() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- concat!(
- r#"import "https://localhost/mod.ts";"#,
- r#"import "https://localhost/other.ts?test";"#,
- r#"import "https://localhost/redirect.ts";"#,
- ),
- )
- .add("https://localhost/mod.ts", "export class Mod {}")
- .add("https://localhost/other.ts?test", "export class Other {}")
- .add_redirect(
- "https://localhost/redirect.ts",
- "https://localhost/mod.ts",
- );
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/other.ts?test": "./localhost/other.ts",
- "https://localhost/redirect.ts": "./localhost/mod.ts",
- "https://localhost/": "./localhost/",
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/mod.ts", "export class Mod {}"),
- ("/vendor/localhost/other.ts", "export class Other {}"),
- ]),
- );
- }
-
- #[tokio::test]
- async fn remote_specifiers() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- concat!(
- r#"import "https://localhost/mod.ts";"#,
- r#"import "https://other/mod.ts";"#,
- ),
- )
- .add(
- "https://localhost/mod.ts",
- concat!(
- "export * from './other.ts';",
- "export * from './redirect.ts';",
- "export * from '/absolute.ts';",
- ),
- )
- .add("https://localhost/other.ts", "export class Other {}")
- .add_redirect(
- "https://localhost/redirect.ts",
- "https://localhost/other.ts",
- )
- .add("https://localhost/absolute.ts", "export class Absolute {}")
- .add("https://other/mod.ts", "export * from './sub/mod.ts';")
- .add(
- "https://other/sub/mod.ts",
- concat!(
- "export * from '../sub2/mod.ts';",
- "export * from '../sub2/other?asdf';",
- // reference a path on a different origin
- "export * from 'https://localhost/other.ts';",
- "export * from 'https://localhost/redirect.ts';",
- ),
- )
- .add("https://other/sub2/mod.ts", "export class Mod {}")
- .add_with_headers(
- "https://other/sub2/other?asdf",
- "export class Other {}",
- &[("content-type", "application/javascript")],
- );
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/",
- "https://localhost/redirect.ts": "./localhost/other.ts",
- "https://other/": "./other/",
- },
- "scopes": {
- "./localhost/": {
- "./localhost/redirect.ts": "./localhost/other.ts",
- "/absolute.ts": "./localhost/absolute.ts",
- },
- "./other/": {
- "./other/sub2/other?asdf": "./other/sub2/other.js"
- }
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/absolute.ts", "export class Absolute {}"),
- (
- "/vendor/localhost/mod.ts",
- concat!(
- "export * from './other.ts';",
- "export * from './redirect.ts';",
- "export * from '/absolute.ts';",
- )
- ),
- ("/vendor/localhost/other.ts", "export class Other {}"),
- ("/vendor/other/mod.ts", "export * from './sub/mod.ts';"),
- (
- "/vendor/other/sub/mod.ts",
- concat!(
- "export * from '../sub2/mod.ts';",
- "export * from '../sub2/other?asdf';",
- "export * from 'https://localhost/other.ts';",
- "export * from 'https://localhost/redirect.ts';",
- )
- ),
- ("/vendor/other/sub2/mod.ts", "export class Mod {}"),
- ("/vendor/other/sub2/other.js", "export class Other {}"),
- ]),
- );
- }
-
- #[tokio::test]
- async fn remote_redirect_entrypoint() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- concat!(
- "import * as test from 'https://x.nest.land/Yenv@1.0.0/mod.ts';\n",
- "console.log(test)",
- ),
- )
- .add_redirect("https://x.nest.land/Yenv@1.0.0/mod.ts", "https://arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts")
- .add(
- "https://arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts",
- "export * from './src/mod.ts'",
- )
- .add(
- "https://arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/src/mod.ts",
- "export class Test {}",
- );
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://x.nest.land/Yenv@1.0.0/mod.ts": "./arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts",
- "https://arweave.net/": "./arweave.net/"
- },
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/mod.ts", "export * from './src/mod.ts'"),
- (
- "/vendor/arweave.net/VFtWNW3QZ-7__v7c7kck22eFI24OuK1DFzyQHKoZ9AE/src/mod.ts",
- "export class Test {}",
- ),
- ]),
- );
- }
-
- #[tokio::test]
- async fn same_target_filename_specifiers() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- concat!(
- r#"import "https://localhost/MOD.TS";"#,
- r#"import "https://localhost/mod.TS";"#,
- r#"import "https://localhost/mod.ts";"#,
- r#"import "https://localhost/mod.ts?test";"#,
- r#"import "https://localhost/CAPS.TS";"#,
- ),
- )
- .add("https://localhost/MOD.TS", "export class Mod {}")
- .add("https://localhost/mod.TS", "export class Mod2 {}")
- .add("https://localhost/mod.ts", "export class Mod3 {}")
- .add("https://localhost/mod.ts?test", "export class Mod4 {}")
- .add("https://localhost/CAPS.TS", "export class Caps {}");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/mod.TS": "./localhost/mod_2.TS",
- "https://localhost/mod.ts": "./localhost/mod_3.ts",
- "https://localhost/mod.ts?test": "./localhost/mod_4.ts",
- "https://localhost/": "./localhost/",
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/CAPS.TS", "export class Caps {}"),
- ("/vendor/localhost/MOD.TS", "export class Mod {}"),
- ("/vendor/localhost/mod_2.TS", "export class Mod2 {}"),
- ("/vendor/localhost/mod_3.ts", "export class Mod3 {}"),
- ("/vendor/localhost/mod_4.ts", "export class Mod4 {}"),
- ]),
- );
- }
-
- #[tokio::test]
- async fn multiple_entrypoints() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .add_entry_point("/test.deps.ts")
- .with_loader(|loader| {
- loader
- .add("/mod.ts", r#"import "https://localhost/mod.ts";"#)
- .add(
- "/test.deps.ts",
- r#"export * from "https://localhost/test.ts";"#,
- )
- .add("https://localhost/mod.ts", "export class Mod {}")
- .add("https://localhost/test.ts", "export class Test {}");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/",
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/mod.ts", "export class Mod {}"),
- ("/vendor/localhost/test.ts", "export class Test {}"),
- ]),
- );
- }
-
- #[tokio::test]
- async fn json_module() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- r#"import data from "https://localhost/data.json" assert { type: "json" };"#,
- )
- .add("https://localhost/data.json", "{ \"a\": \"b\" }");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/"
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[("/vendor/localhost/data.json", "{ \"a\": \"b\" }"),]),
- );
- }
-
- #[tokio::test]
- async fn data_urls() {
- let mut builder = VendorTestBuilder::with_default_setup();
-
- let mod_file_text = r#"import * as b from "data:application/typescript,export%20*%20from%20%22https://localhost/mod.ts%22;";"#;
-
- let output = builder
- .with_loader(|loader| {
- loader
- .add("/mod.ts", mod_file_text)
- .add("https://localhost/mod.ts", "export class Example {}");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/"
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[("/vendor/localhost/mod.ts", "export class Example {}"),]),
- );
- }
-
- #[tokio::test]
- async fn x_typescript_types_no_default() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add("/mod.ts", r#"import "https://localhost/mod.js";"#)
- .add_with_headers(
- "https://localhost/mod.js",
- "export class Mod {}",
- &[("x-typescript-types", "https://localhost/mod.d.ts")],
- )
- .add("https://localhost/mod.d.ts", "export class Mod {}");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/"
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/mod.d.ts", "export class Mod {}"),
- (
- "/vendor/localhost/mod.js",
- concat!(
- "// @deno-types=\"https://localhost/mod.d.ts\"\n",
- "export * from \"./mod.proxied.js\";\n"
- )
- ),
- ("/vendor/localhost/mod.proxied.js", "export class Mod {}"),
- ]),
- );
- }
-
- #[tokio::test]
- async fn x_typescript_types_default_export() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add("/mod.ts", r#"import "https://localhost/mod.js";"#)
- .add_with_headers(
- "https://localhost/mod.js",
- "export default class Mod {}",
- &[("x-typescript-types", "https://localhost/mod.d.ts")],
- )
- .add("https://localhost/mod.d.ts", "export default class Mod {}");
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/"
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/mod.d.ts", "export default class Mod {}"),
- (
- "/vendor/localhost/mod.js",
- concat!(
- "// @deno-types=\"https://localhost/mod.d.ts\"\n",
- "export * from \"./mod.proxied.js\";\n",
- "export { default } from \"./mod.proxied.js\";\n",
- )
- ),
- (
- "/vendor/localhost/mod.proxied.js",
- "export default class Mod {}"
- ),
- ]),
- );
- }
-
- #[tokio::test]
- async fn subdir() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- r#"import "http://localhost:4545/sub/logger/mod.ts?testing";"#,
- )
- .add(
- "http://localhost:4545/sub/logger/mod.ts?testing",
- "export * from './logger.ts?test';",
- )
- .add(
- "http://localhost:4545/sub/logger/logger.ts?test",
- "export class Logger {}",
- );
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "http://localhost:4545/sub/logger/mod.ts?testing": "./localhost_4545/sub/logger/mod.ts",
- "http://localhost:4545/": "./localhost_4545/",
- },
- "scopes": {
- "./localhost_4545/": {
- "./localhost_4545/sub/logger/logger.ts?test": "./localhost_4545/sub/logger/logger.ts"
- }
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- (
- "/vendor/localhost_4545/sub/logger/logger.ts",
- "export class Logger {}",
- ),
- (
- "/vendor/localhost_4545/sub/logger/mod.ts",
- "export * from './logger.ts?test';"
- ),
- ]),
- );
- }
-
- #[tokio::test]
- async fn same_origin_absolute_with_redirect() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add(
- "/mod.ts",
- r#"import "https://localhost/subdir/sub/mod.ts";"#,
- )
- .add(
- "https://localhost/subdir/sub/mod.ts",
- "import 'https://localhost/std/hash/mod.ts'",
- )
- .add_redirect(
- "https://localhost/std/hash/mod.ts",
- "https://localhost/std@0.1.0/hash/mod.ts",
- )
- .add(
- "https://localhost/std@0.1.0/hash/mod.ts",
- "export class Test {}",
- );
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/std/hash/mod.ts": "./localhost/std@0.1.0/hash/mod.ts",
- "https://localhost/": "./localhost/",
- },
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- (
- "/vendor/localhost/std@0.1.0/hash/mod.ts",
- "export class Test {}"
- ),
- (
- "/vendor/localhost/subdir/sub/mod.ts",
- "import 'https://localhost/std/hash/mod.ts'"
- ),
- ]),
- );
- }
-
- #[tokio::test]
- async fn remote_relative_specifier_with_scheme_like_folder_name() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let output = builder
- .with_loader(|loader| {
- loader
- .add("/mod.ts", "import 'https://localhost/mod.ts';")
- .add(
- "https://localhost/mod.ts",
- "import './npm:test@1.0.0/test/test!cjs?test';import './npm:test@1.0.0/mod.ts';",
- )
- .add(
- "https://localhost/npm:test@1.0.0/mod.ts",
- "console.log(4);",
- )
- .add_with_headers(
- "https://localhost/npm:test@1.0.0/test/test!cjs?test",
- "console.log(5);",
- &[("content-type", "application/javascript")],
- );
- })
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/"
- },
- "scopes": {
- "./localhost/": {
- "./localhost/npm:test@1.0.0/mod.ts": "./localhost/npm_test@1.0.0/mod.ts",
- "./localhost/npm:test@1.0.0/test/test!cjs?test": "./localhost/npm_test@1.0.0/test/test!cjs.js",
- "./localhost/npm_test@1.0.0/test/test!cjs?test": "./localhost/npm_test@1.0.0/test/test!cjs.js"
- }
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- (
- "/vendor/localhost/mod.ts",
- "import './npm:test@1.0.0/test/test!cjs?test';import './npm:test@1.0.0/mod.ts';"
- ),
- ("/vendor/localhost/npm_test@1.0.0/mod.ts", "console.log(4);"),
- (
- "/vendor/localhost/npm_test@1.0.0/test/test!cjs.js",
- "console.log(5);"
- ),
- ]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_basic() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map2.json");
- original_import_map
- .imports_mut()
- .append(
- "https://localhost/mod.ts".to_string(),
- "./local_vendor/mod.ts".to_string(),
- )
- .unwrap();
- let local_vendor_scope = original_import_map
- .get_or_append_scope_mut("./local_vendor/")
- .unwrap();
- local_vendor_scope
- .append(
- "https://localhost/logger.ts".to_string(),
- "./local_vendor/logger.ts".to_string(),
- )
- .unwrap();
- local_vendor_scope
- .append(
- "/console_logger.ts".to_string(),
- "./local_vendor/console_logger.ts".to_string(),
- )
- .unwrap();
-
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'https://localhost/mod.ts'; import 'https://localhost/other.ts';");
- loader.add("/local_vendor/mod.ts", "import 'https://localhost/logger.ts'; import '/console_logger.ts'; console.log(5);");
- loader.add("/local_vendor/logger.ts", "export class Logger {}");
- loader.add("/local_vendor/console_logger.ts", "export class ConsoleLogger {}");
- loader.add("https://localhost/mod.ts", "console.log(6);");
- loader.add("https://localhost/other.ts", "import './mod.ts';");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/mod.ts": "../local_vendor/mod.ts",
- "https://localhost/": "./localhost/"
- },
- "scopes": {
- "../local_vendor/": {
- "https://localhost/logger.ts": "../local_vendor/logger.ts",
- "/console_logger.ts": "../local_vendor/console_logger.ts",
- },
- "./localhost/": {
- "./localhost/mod.ts": "../local_vendor/mod.ts",
- },
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[("/vendor/localhost/other.ts", "import './mod.ts';")]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_remote_dep_bare_specifier() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map2.json");
- original_import_map
- .imports_mut()
- .append(
- "twind".to_string(),
- "https://localhost/twind.ts".to_string(),
- )
- .unwrap();
-
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'https://remote/mod.ts';");
- loader.add("https://remote/mod.ts", "import 'twind';");
- loader.add("https://localhost/twind.ts", "export class Test {}");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/",
- "https://remote/": "./remote/"
- },
- "scopes": {
- "./remote/": {
- "twind": "./localhost/twind.ts"
- },
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/twind.ts", "export class Test {}"),
- ("/vendor/remote/mod.ts", "import 'twind';"),
- ]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_mapped_bare_specifier() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map.json");
- let imports = original_import_map.imports_mut();
- imports
- .append("$fresh".to_string(), "https://localhost/fresh".to_string())
- .unwrap();
- imports
- .append("std/".to_string(), "https://deno.land/std/".to_string())
- .unwrap();
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'std/mod.ts'; import '$fresh';");
- loader.add("https://deno.land/std/mod.ts", "export function test() {}");
- loader.add_with_headers(
- "https://localhost/fresh",
- "export function fresh() {}",
- &[("content-type", "application/typescript")],
- );
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://deno.land/": "./deno.land/",
- "https://localhost/": "./localhost/",
- "$fresh": "./localhost/fresh.ts",
- "std/mod.ts": "./deno.land/std/mod.ts",
- },
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/deno.land/std/mod.ts", "export function test() {}"),
- ("/vendor/localhost/fresh.ts", "export function fresh() {}")
- ]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_remote_absolute_specifier_local() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map.json");
- original_import_map
- .imports_mut()
- .append(
- "https://localhost/logger.ts?test".to_string(),
- "./local/logger.ts".to_string(),
- )
- .unwrap();
-
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'https://localhost/mod.ts'; import 'https://localhost/logger.ts?test';");
- loader.add("/local/logger.ts", "export class Logger {}");
- // absolute specifier in a remote module that will point at ./local/logger.ts
- loader.add("https://localhost/mod.ts", "import '/logger.ts?test';");
- loader.add("https://localhost/logger.ts?test", "export class Logger {}");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/logger.ts?test": "../local/logger.ts",
- "https://localhost/": "./localhost/",
- },
- "scopes": {
- "./localhost/": {
- "/logger.ts?test": "../local/logger.ts",
- },
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[("/vendor/localhost/mod.ts", "import '/logger.ts?test';")]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_imports_output_dir() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map.json");
- original_import_map
- .imports_mut()
- .append(
- "std/mod.ts".to_string(),
- "./vendor/deno.land/std/mod.ts".to_string(),
- )
- .unwrap();
- let err = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'std/mod.ts';");
- loader.add("/vendor/deno.land/std/mod.ts", "export function f() {}");
- loader.add("https://deno.land/std/mod.ts", "export function f() {}");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .err()
- .unwrap();
-
- assert_eq!(
- err.to_string(),
- concat!(
- "Providing an existing import map with entries for the output ",
- "directory is not supported ",
- "(\"std/mod.ts\": \"./vendor/deno.land/std/mod.ts\").",
- )
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_scopes_entry_output_dir() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map.json");
- let scopes = original_import_map
- .get_or_append_scope_mut("./other/")
- .unwrap();
- scopes
- .append("/mod.ts".to_string(), "./vendor/mod.ts".to_string())
- .unwrap();
- let err = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "console.log(5);");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .err()
- .unwrap();
-
- assert_eq!(
- err.to_string(),
- concat!(
- "Providing an existing import map with entries for the output ",
- "directory is not supported ",
- "(\"/mod.ts\": \"./vendor/mod.ts\").",
- )
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_scopes_key_output_dir() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map.json");
- let scopes = original_import_map
- .get_or_append_scope_mut("./vendor/")
- .unwrap();
- scopes
- .append("/mod.ts".to_string(), "./vendor/mod.ts".to_string())
- .unwrap();
- let err = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "console.log(5);");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .err()
- .unwrap();
-
- assert_eq!(
- err.to_string(),
- concat!(
- "Providing an existing import map with a scope for the output ",
- "directory is not supported (\"./vendor/\").",
- )
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_http_key() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let mut original_import_map = builder.new_import_map("/import_map.json");
- original_import_map
- .imports_mut()
- .append(
- "http/".to_string(),
- "https://deno.land/std/http/".to_string(),
- )
- .unwrap();
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'http/mod.ts';");
- loader.add("https://deno.land/std/http/mod.ts", "console.log(5);");
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "http/mod.ts": "./deno.land/std/http/mod.ts",
- "https://deno.land/": "./deno.land/",
- }
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[("/vendor/deno.land/std/http/mod.ts", "console.log(5);")]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_jsx_import_source_jsx_files() {
- let mut builder = VendorTestBuilder::default();
- builder.add_entry_point("/mod.tsx");
- builder.set_jsx_import_source_config(JsxImportSourceConfig {
- default_specifier: Some("preact".to_string()),
- default_types_specifier: None,
- module: "jsx-runtime".to_string(),
- base_url: builder.resolve_to_url("/deno.json"),
- });
- let mut original_import_map = builder.new_import_map("/import_map.json");
- let imports = original_import_map.imports_mut();
- imports
- .append(
- "preact/".to_string(),
- "https://localhost/preact/".to_string(),
- )
- .unwrap();
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.tsx", "const myComponent = <div></div>;");
- loader.add_with_headers(
- "https://localhost/preact/jsx-runtime",
- "export function stuff() {}",
- &[("content-type", "application/typescript")],
- );
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/",
- "preact/jsx-runtime": "./localhost/preact/jsx-runtime.ts",
- },
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[(
- "/vendor/localhost/preact/jsx-runtime.ts",
- "export function stuff() {}"
- ),]),
- );
- }
-
- #[tokio::test]
- async fn existing_import_map_jsx_import_source_no_jsx_files() {
- let mut builder = VendorTestBuilder::default();
- builder.add_entry_point("/mod.ts");
- builder.set_jsx_import_source_config(JsxImportSourceConfig {
- default_specifier: Some("preact".to_string()),
- default_types_specifier: None,
- module: "jsx-runtime".to_string(),
- base_url: builder.resolve_to_url("/deno.json"),
- });
- let mut original_import_map = builder.new_import_map("/import_map.json");
- let imports = original_import_map.imports_mut();
- imports
- .append(
- "preact/".to_string(),
- "https://localhost/preact/".to_string(),
- )
- .unwrap();
- let output = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'https://localhost/mod.ts';");
- loader.add("https://localhost/mod.ts", "console.log(1)");
- loader.add_with_headers(
- "https://localhost/preact/jsx-runtime",
- "export function stuff() {}",
- &[("content-type", "application/typescript")],
- );
- })
- .set_original_import_map(original_import_map)
- .build()
- .await
- .unwrap();
-
- assert_eq!(
- output.import_map,
- Some(json!({
- "imports": {
- "https://localhost/": "./localhost/",
- "preact/jsx-runtime": "./localhost/preact/jsx-runtime.ts"
- },
- }))
- );
- assert_eq!(
- output.files,
- to_file_vec(&[
- ("/vendor/localhost/mod.ts", "console.log(1)"),
- (
- "/vendor/localhost/preact/jsx-runtime.ts",
- "export function stuff() {}"
- ),
- ]),
- );
- }
-
- #[tokio::test]
- async fn vendor_file_fails_loading_dynamic_import() {
- let mut builder = VendorTestBuilder::with_default_setup();
- let err = builder
- .with_loader(|loader| {
- loader.add("/mod.ts", "import 'https://localhost/mod.ts';");
- loader.add("https://localhost/mod.ts", "await import('./test.ts');");
- loader.add_failure(
- "https://localhost/test.ts",
- "500 Internal Server Error",
- );
- })
- .build()
- .await
- .err()
- .unwrap();
-
- assert_eq!(
- test_util::strip_ansi_codes(&err.to_string()),
- concat!(
- "500 Internal Server Error\n",
- " at https://localhost/mod.ts:1:14"
- )
- );
- }
-
- fn to_file_vec(items: &[(&str, &str)]) -> Vec<(String, String)> {
- items
- .iter()
- .map(|(f, t)| (f.to_string(), t.to_string()))
- .collect()
- }
-}
diff --git a/cli/tools/vendor/import_map.rs b/cli/tools/vendor/import_map.rs
deleted file mode 100644
index 644e84a7b..000000000
--- a/cli/tools/vendor/import_map.rs
+++ /dev/null
@@ -1,508 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use deno_ast::LineAndColumnIndex;
-use deno_ast::ModuleSpecifier;
-use deno_ast::SourceTextInfo;
-use deno_core::error::AnyError;
-use deno_graph::source::ResolutionMode;
-use deno_graph::Module;
-use deno_graph::ModuleGraph;
-use deno_graph::Position;
-use deno_graph::Range;
-use deno_graph::Resolution;
-use import_map::ImportMap;
-use import_map::SpecifierMap;
-use indexmap::IndexMap;
-use log::warn;
-
-use crate::args::JsxImportSourceConfig;
-use crate::cache::ParsedSourceCache;
-
-use super::mappings::Mappings;
-use super::specifiers::is_remote_specifier;
-use super::specifiers::is_remote_specifier_text;
-
-struct ImportMapBuilder<'a> {
- base_dir: &'a ModuleSpecifier,
- mappings: &'a Mappings,
- imports: ImportsBuilder<'a>,
- scopes: IndexMap<String, ImportsBuilder<'a>>,
-}
-
-impl<'a> ImportMapBuilder<'a> {
- pub fn new(base_dir: &'a ModuleSpecifier, mappings: &'a Mappings) -> Self {
- ImportMapBuilder {
- base_dir,
- mappings,
- imports: ImportsBuilder::new(base_dir, mappings),
- scopes: Default::default(),
- }
- }
-
- pub fn base_dir(&self) -> &ModuleSpecifier {
- self.base_dir
- }
-
- pub fn scope(
- &mut self,
- base_specifier: &ModuleSpecifier,
- ) -> &mut ImportsBuilder<'a> {
- self
- .scopes
- .entry(
- self
- .mappings
- .relative_specifier_text(self.base_dir, base_specifier),
- )
- .or_insert_with(|| ImportsBuilder::new(self.base_dir, self.mappings))
- }
-
- pub fn into_import_map(
- self,
- maybe_original_import_map: Option<&ImportMap>,
- ) -> ImportMap {
- fn get_local_imports(
- new_relative_path: &str,
- original_imports: &SpecifierMap,
- ) -> Vec<(String, String)> {
- let mut result = Vec::new();
- for entry in original_imports.entries() {
- if let Some(raw_value) = entry.raw_value {
- if raw_value.starts_with("./") || raw_value.starts_with("../") {
- let sub_index = raw_value.find('/').unwrap() + 1;
- result.push((
- entry.raw_key.to_string(),
- format!("{}{}", new_relative_path, &raw_value[sub_index..]),
- ));
- }
- }
- }
- result
- }
-
- fn add_local_imports<'a>(
- new_relative_path: &str,
- original_imports: &SpecifierMap,
- get_new_imports: impl FnOnce() -> &'a mut SpecifierMap,
- ) {
- let local_imports =
- get_local_imports(new_relative_path, original_imports);
- if !local_imports.is_empty() {
- let new_imports = get_new_imports();
- for (key, value) in local_imports {
- if let Err(warning) = new_imports.append(key, value) {
- warn!("{}", warning);
- }
- }
- }
- }
-
- let mut import_map = ImportMap::new(self.base_dir.clone());
-
- if let Some(original_im) = maybe_original_import_map {
- let original_base_dir = ModuleSpecifier::from_directory_path(
- original_im
- .base_url()
- .to_file_path()
- .unwrap()
- .parent()
- .unwrap(),
- )
- .unwrap();
- let new_relative_path = self
- .mappings
- .relative_specifier_text(self.base_dir, &original_base_dir);
- // add the imports
- add_local_imports(&new_relative_path, original_im.imports(), || {
- import_map.imports_mut()
- });
-
- for scope in original_im.scopes() {
- if scope.raw_key.starts_with("./") || scope.raw_key.starts_with("../") {
- let sub_index = scope.raw_key.find('/').unwrap() + 1;
- let new_key =
- format!("{}{}", new_relative_path, &scope.raw_key[sub_index..]);
- add_local_imports(&new_relative_path, scope.imports, || {
- import_map.get_or_append_scope_mut(&new_key).unwrap()
- });
- }
- }
- }
-
- let imports = import_map.imports_mut();
- for (key, value) in self.imports.imports {
- if !imports.contains(&key) {
- imports.append(key, value).unwrap();
- }
- }
-
- for (scope_key, scope_value) in self.scopes {
- if !scope_value.imports.is_empty() {
- let imports = import_map.get_or_append_scope_mut(&scope_key).unwrap();
- for (key, value) in scope_value.imports {
- if !imports.contains(&key) {
- imports.append(key, value).unwrap();
- }
- }
- }
- }
-
- import_map
- }
-}
-
-struct ImportsBuilder<'a> {
- base_dir: &'a ModuleSpecifier,
- mappings: &'a Mappings,
- imports: IndexMap<String, String>,
-}
-
-impl<'a> ImportsBuilder<'a> {
- pub fn new(base_dir: &'a ModuleSpecifier, mappings: &'a Mappings) -> Self {
- Self {
- base_dir,
- mappings,
- imports: Default::default(),
- }
- }
-
- pub fn add(&mut self, key: String, specifier: &ModuleSpecifier) {
- let value = self
- .mappings
- .relative_specifier_text(self.base_dir, specifier);
-
- // skip creating identity entries
- if key != value {
- self.imports.insert(key, value);
- }
- }
-}
-
-pub struct BuildImportMapInput<'a> {
- pub base_dir: &'a ModuleSpecifier,
- pub modules: &'a [&'a Module],
- pub graph: &'a ModuleGraph,
- pub mappings: &'a Mappings,
- pub maybe_original_import_map: Option<&'a ImportMap>,
- pub maybe_jsx_import_source: Option<&'a JsxImportSourceConfig>,
- pub resolver: &'a dyn deno_graph::source::Resolver,
- pub parsed_source_cache: &'a ParsedSourceCache,
-}
-
-pub fn build_import_map(
- input: BuildImportMapInput<'_>,
-) -> Result<String, AnyError> {
- let BuildImportMapInput {
- base_dir,
- modules,
- graph,
- mappings,
- maybe_original_import_map,
- maybe_jsx_import_source,
- resolver,
- parsed_source_cache,
- } = input;
- let mut builder = ImportMapBuilder::new(base_dir, mappings);
- visit_modules(graph, modules, mappings, &mut builder, parsed_source_cache)?;
-
- for base_specifier in mappings.base_specifiers() {
- builder
- .imports
- .add(base_specifier.to_string(), base_specifier);
- }
-
- // add the jsx import source to the destination import map, if mapped in the original import map
- if let Some(jsx_import_source) = maybe_jsx_import_source {
- if let Some(specifier_text) = jsx_import_source.maybe_specifier_text() {
- if let Ok(resolved_url) = resolver.resolve(
- &specifier_text,
- &deno_graph::Range {
- specifier: jsx_import_source.base_url.clone(),
- start: deno_graph::Position::zeroed(),
- end: deno_graph::Position::zeroed(),
- },
- ResolutionMode::Execution,
- ) {
- builder.imports.add(specifier_text, &resolved_url);
- }
- }
- }
-
- Ok(builder.into_import_map(maybe_original_import_map).to_json())
-}
-
-fn visit_modules(
- graph: &ModuleGraph,
- modules: &[&Module],
- mappings: &Mappings,
- import_map: &mut ImportMapBuilder,
- parsed_source_cache: &ParsedSourceCache,
-) -> Result<(), AnyError> {
- for module in modules {
- let module = match module {
- Module::Js(module) => module,
- // skip visiting Json modules as they are leaves
- Module::Json(_)
- | Module::Npm(_)
- | Module::Node(_)
- | Module::External(_) => continue,
- };
-
- let parsed_source =
- parsed_source_cache.get_parsed_source_from_js_module(module)?;
- let text_info = parsed_source.text_info_lazy().clone();
-
- for dep in module.dependencies.values() {
- visit_resolution(
- &dep.maybe_code,
- graph,
- import_map,
- &module.specifier,
- mappings,
- &text_info,
- &module.source,
- );
- visit_resolution(
- &dep.maybe_type,
- graph,
- import_map,
- &module.specifier,
- mappings,
- &text_info,
- &module.source,
- );
- }
-
- if let Some(types_dep) = &module.maybe_types_dependency {
- visit_resolution(
- &types_dep.dependency,
- graph,
- import_map,
- &module.specifier,
- mappings,
- &text_info,
- &module.source,
- );
- }
- }
-
- Ok(())
-}
-
-fn visit_resolution(
- resolution: &Resolution,
- graph: &ModuleGraph,
- import_map: &mut ImportMapBuilder,
- referrer: &ModuleSpecifier,
- mappings: &Mappings,
- text_info: &SourceTextInfo,
- source_text: &str,
-) {
- if let Some(resolved) = resolution.ok() {
- let text = text_from_range(text_info, source_text, &resolved.range);
- // if the text is empty then it's probably an x-TypeScript-types
- if !text.is_empty() {
- handle_dep_specifier(
- text,
- &resolved.specifier,
- graph,
- import_map,
- referrer,
- mappings,
- );
- }
- }
-}
-
-fn handle_dep_specifier(
- text: &str,
- unresolved_specifier: &ModuleSpecifier,
- graph: &ModuleGraph,
- import_map: &mut ImportMapBuilder,
- referrer: &ModuleSpecifier,
- mappings: &Mappings,
-) {
- let specifier = match graph.get(unresolved_specifier) {
- Some(module) => module.specifier().clone(),
- // Ignore when None. The graph was previous validated so this is a
- // dynamic import that was missing and is ignored for vendoring
- None => return,
- };
- // check if it's referencing a remote module
- if is_remote_specifier(&specifier) {
- handle_remote_dep_specifier(
- text,
- unresolved_specifier,
- &specifier,
- import_map,
- referrer,
- mappings,
- )
- } else if specifier.scheme() == "file" {
- handle_local_dep_specifier(
- text,
- unresolved_specifier,
- &specifier,
- import_map,
- referrer,
- mappings,
- );
- }
-}
-
-fn handle_remote_dep_specifier(
- text: &str,
- unresolved_specifier: &ModuleSpecifier,
- specifier: &ModuleSpecifier,
- import_map: &mut ImportMapBuilder,
- referrer: &ModuleSpecifier,
- mappings: &Mappings,
-) {
- if is_remote_specifier_text(text) {
- let base_specifier = mappings.base_specifier(specifier);
- if text.starts_with(base_specifier.as_str()) {
- let sub_path = &text[base_specifier.as_str().len()..];
- let relative_text =
- mappings.relative_specifier_text(base_specifier, specifier);
- let expected_sub_path = relative_text.trim_start_matches("./");
- if expected_sub_path != sub_path {
- import_map.imports.add(text.to_string(), specifier);
- }
- } else {
- // it's probably a redirect. Add it explicitly to the import map
- import_map.imports.add(text.to_string(), specifier);
- }
- } else {
- let expected_relative_specifier_text =
- mappings.relative_specifier_text(referrer, specifier);
- if expected_relative_specifier_text == text {
- return;
- }
-
- if !is_remote_specifier(referrer) {
- // local module referencing a remote module using
- // non-remote specifier text means it was something in
- // the original import map, so add a mapping to it
- import_map.imports.add(text.to_string(), specifier);
- return;
- }
-
- let base_referrer = mappings.base_specifier(referrer);
- let base_dir = import_map.base_dir().clone();
- let imports = import_map.scope(base_referrer);
- if text.starts_with("./") || text.starts_with("../") {
- // resolve relative specifier key
- let mut local_base_specifier = mappings.local_uri(base_referrer);
- local_base_specifier = local_base_specifier
- // path includes "/" so make it relative
- .join(&format!(".{}", unresolved_specifier.path()))
- .unwrap_or_else(|_| {
- panic!(
- "Error joining {} to {}",
- unresolved_specifier.path(),
- local_base_specifier
- )
- });
- local_base_specifier.set_query(unresolved_specifier.query());
-
- imports.add(
- mappings.relative_specifier_text(&base_dir, &local_base_specifier),
- specifier,
- );
-
- // add a mapping that uses the local directory name and the remote
- // filename in order to support files importing this relatively
- imports.add(
- {
- let local_path = mappings.local_path(specifier);
- let mut value =
- ModuleSpecifier::from_directory_path(local_path.parent().unwrap())
- .unwrap();
- value.set_query(specifier.query());
- value.set_path(&format!(
- "{}{}",
- value.path(),
- specifier.path_segments().unwrap().last().unwrap(),
- ));
- mappings.relative_specifier_text(&base_dir, &value)
- },
- specifier,
- );
- } else {
- // absolute (`/`) or bare specifier should be left as-is
- imports.add(text.to_string(), specifier);
- }
- }
-}
-
-fn handle_local_dep_specifier(
- text: &str,
- unresolved_specifier: &ModuleSpecifier,
- specifier: &ModuleSpecifier,
- import_map: &mut ImportMapBuilder,
- referrer: &ModuleSpecifier,
- mappings: &Mappings,
-) {
- if !is_remote_specifier(referrer) {
- // do not handle local modules referencing local modules
- return;
- }
-
- // The remote module is referencing a local file. This could occur via an
- // existing import map. In this case, we'll have to add an import map
- // entry in order to map the path back to the local path once vendored.
- let base_dir = import_map.base_dir().clone();
- let base_specifier = mappings.base_specifier(referrer);
- let imports = import_map.scope(base_specifier);
-
- if text.starts_with("./") || text.starts_with("../") {
- let referrer_local_uri = mappings.local_uri(referrer);
- let mut specifier_local_uri =
- referrer_local_uri.join(text).unwrap_or_else(|_| {
- panic!(
- "Error joining {} to {}",
- unresolved_specifier.path(),
- referrer_local_uri
- )
- });
- specifier_local_uri.set_query(unresolved_specifier.query());
-
- imports.add(
- mappings.relative_specifier_text(&base_dir, &specifier_local_uri),
- specifier,
- );
- } else {
- imports.add(text.to_string(), specifier);
- }
-}
-
-fn text_from_range<'a>(
- text_info: &SourceTextInfo,
- text: &'a str,
- range: &Range,
-) -> &'a str {
- let result = &text[byte_range(text_info, range)];
- if result.starts_with('"') || result.starts_with('\'') {
- // remove the quotes
- &result[1..result.len() - 1]
- } else {
- result
- }
-}
-
-fn byte_range(
- text_info: &SourceTextInfo,
- range: &Range,
-) -> std::ops::Range<usize> {
- let start = byte_index(text_info, &range.start);
- let end = byte_index(text_info, &range.end);
- start..end
-}
-
-fn byte_index(text_info: &SourceTextInfo, pos: &Position) -> usize {
- // todo(https://github.com/denoland/deno_graph/issues/79): use byte indexes all the way down
- text_info.loc_to_source_pos(LineAndColumnIndex {
- line_index: pos.line,
- column_index: pos.character,
- }) - text_info.range().start
-}
diff --git a/cli/tools/vendor/mappings.rs b/cli/tools/vendor/mappings.rs
deleted file mode 100644
index 6d2722b89..000000000
--- a/cli/tools/vendor/mappings.rs
+++ /dev/null
@@ -1,255 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use std::collections::HashMap;
-use std::collections::HashSet;
-use std::path::Path;
-use std::path::PathBuf;
-
-use deno_ast::MediaType;
-use deno_ast::ModuleSpecifier;
-use deno_core::error::AnyError;
-use deno_graph::Module;
-use deno_graph::ModuleGraph;
-use deno_graph::Position;
-
-use crate::util::path::path_with_stem_suffix;
-use crate::util::path::relative_specifier;
-
-use super::specifiers::dir_name_for_root;
-use super::specifiers::get_unique_path;
-use super::specifiers::make_url_relative;
-use super::specifiers::partition_by_root_specifiers;
-use super::specifiers::sanitize_filepath;
-
-pub struct ProxiedModule {
- pub output_path: PathBuf,
- pub declaration_specifier: ModuleSpecifier,
-}
-
-/// Constructs and holds the remote specifier to local path mappings.
-pub struct Mappings {
- mappings: HashMap<ModuleSpecifier, PathBuf>,
- base_specifiers: Vec<ModuleSpecifier>,
- proxies: HashMap<ModuleSpecifier, ProxiedModule>,
-}
-
-impl Mappings {
- pub fn from_remote_modules(
- graph: &ModuleGraph,
- remote_modules: &[&Module],
- output_dir: &Path,
- ) -> Result<Self, AnyError> {
- let partitioned_specifiers = partition_by_root_specifiers(
- remote_modules.iter().map(|m| m.specifier()),
- );
- let mut mapped_paths = HashSet::new();
- let mut mappings = HashMap::new();
- let mut proxies = HashMap::new();
- let mut base_specifiers = Vec::new();
-
- for (root, specifiers) in partitioned_specifiers.into_iter() {
- let base_dir = get_unique_path(
- output_dir.join(dir_name_for_root(&root)),
- &mut mapped_paths,
- );
- for specifier in specifiers {
- let module = graph.get(&specifier).unwrap();
- let media_type = match module {
- Module::Js(module) => module.media_type,
- Module::Json(_) => MediaType::Json,
- Module::Node(_) | Module::Npm(_) | Module::External(_) => continue,
- };
- let sub_path = sanitize_filepath(&make_url_relative(&root, &{
- let mut specifier = specifier.clone();
- specifier.set_query(None);
- specifier
- })?);
- let new_path = path_with_extension(
- &base_dir.join(if cfg!(windows) {
- sub_path.replace('/', "\\")
- } else {
- sub_path
- }),
- &media_type.as_ts_extension()[1..],
- );
- mappings
- .insert(specifier, get_unique_path(new_path, &mut mapped_paths));
- }
- base_specifiers.push(root.clone());
- mappings.insert(root, base_dir);
- }
-
- // resolve all the "proxy" paths to use for when an x-typescript-types header is specified
- for module in remote_modules {
- if let Some(module) = module.js() {
- if let Some(resolved) = &module
- .maybe_types_dependency
- .as_ref()
- .and_then(|d| d.dependency.ok())
- {
- let range = &resolved.range;
- // hack to tell if it's an x-typescript-types header
- let is_ts_types_header = range.start == Position::zeroed()
- && range.end == Position::zeroed();
- if is_ts_types_header {
- let module_path = mappings.get(&module.specifier).unwrap();
- let proxied_path = get_unique_path(
- path_with_stem_suffix(module_path, ".proxied"),
- &mut mapped_paths,
- );
- proxies.insert(
- module.specifier.clone(),
- ProxiedModule {
- output_path: proxied_path,
- declaration_specifier: resolved.specifier.clone(),
- },
- );
- }
- }
- }
- }
-
- Ok(Self {
- mappings,
- base_specifiers,
- proxies,
- })
- }
-
- pub fn local_uri(&self, specifier: &ModuleSpecifier) -> ModuleSpecifier {
- if specifier.scheme() == "file" {
- specifier.clone()
- } else {
- let local_path = self.local_path(specifier);
- if specifier.path().ends_with('/') {
- ModuleSpecifier::from_directory_path(&local_path)
- } else {
- ModuleSpecifier::from_file_path(&local_path)
- }
- .unwrap_or_else(|_| {
- panic!("Could not convert {} to uri.", local_path.display())
- })
- }
- }
-
- pub fn local_path(&self, specifier: &ModuleSpecifier) -> PathBuf {
- if specifier.scheme() == "file" {
- specifier.to_file_path().unwrap()
- } else {
- self
- .mappings
- .get(specifier)
- .unwrap_or_else(|| panic!("Could not find local path for {specifier}"))
- .to_path_buf()
- }
- }
-
- pub fn relative_specifier_text(
- &self,
- from: &ModuleSpecifier,
- to: &ModuleSpecifier,
- ) -> String {
- let from = self.local_uri(from);
- let to = self.local_uri(to);
- relative_specifier(&from, &to).unwrap()
- }
-
- pub fn base_specifiers(&self) -> &Vec<ModuleSpecifier> {
- &self.base_specifiers
- }
-
- pub fn base_specifier(
- &self,
- child_specifier: &ModuleSpecifier,
- ) -> &ModuleSpecifier {
- self
- .base_specifiers
- .iter()
- .find(|s| child_specifier.as_str().starts_with(s.as_str()))
- .unwrap_or_else(|| {
- panic!("Could not find base specifier for {child_specifier}")
- })
- }
-
- pub fn proxied_path(&self, specifier: &ModuleSpecifier) -> Option<PathBuf> {
- self.proxies.get(specifier).map(|s| s.output_path.clone())
- }
-
- pub fn proxied_modules(
- &self,
- ) -> std::collections::hash_map::Iter<'_, ModuleSpecifier, ProxiedModule> {
- self.proxies.iter()
- }
-}
-
-fn path_with_extension(path: &Path, new_ext: &str) -> PathBuf {
- if let Some(file_stem) = path.file_stem().map(|f| f.to_string_lossy()) {
- if let Some(old_ext) = path.extension().map(|f| f.to_string_lossy()) {
- if file_stem.to_lowercase().ends_with(".d") {
- if new_ext.to_lowercase() == format!("d.{}", old_ext.to_lowercase()) {
- // maintain casing
- return path.to_path_buf();
- }
- return path.with_file_name(format!(
- "{}.{}",
- &file_stem[..file_stem.len() - ".d".len()],
- new_ext
- ));
- }
- if new_ext.to_lowercase() == old_ext.to_lowercase() {
- // maintain casing
- return path.to_path_buf();
- }
- let media_type = MediaType::from_path(path);
- if media_type == MediaType::Unknown {
- return path.with_file_name(format!(
- "{}.{}",
- path.file_name().unwrap().to_string_lossy(),
- new_ext
- ));
- }
- }
- }
- path.with_extension(new_ext)
-}
-
-#[cfg(test)]
-mod test {
- use pretty_assertions::assert_eq;
-
- use super::*;
-
- #[test]
- fn test_path_with_extension() {
- assert_eq!(
- path_with_extension(&PathBuf::from("/test.D.TS"), "ts"),
- PathBuf::from("/test.ts")
- );
- assert_eq!(
- path_with_extension(&PathBuf::from("/test.D.MTS"), "js"),
- PathBuf::from("/test.js")
- );
- assert_eq!(
- path_with_extension(&PathBuf::from("/test.D.TS"), "d.ts"),
- // maintains casing
- PathBuf::from("/test.D.TS"),
- );
- assert_eq!(
- path_with_extension(&PathBuf::from("/test.TS"), "ts"),
- // maintains casing
- PathBuf::from("/test.TS"),
- );
- assert_eq!(
- path_with_extension(&PathBuf::from("/test.ts"), "js"),
- PathBuf::from("/test.js")
- );
- assert_eq!(
- path_with_extension(&PathBuf::from("/test.js"), "js"),
- PathBuf::from("/test.js")
- );
- assert_eq!(
- path_with_extension(&PathBuf::from("/chai@1.2.3"), "js"),
- PathBuf::from("/chai@1.2.3.js")
- );
- }
-}
diff --git a/cli/tools/vendor/mod.rs b/cli/tools/vendor/mod.rs
deleted file mode 100644
index 3de08f1d0..000000000
--- a/cli/tools/vendor/mod.rs
+++ /dev/null
@@ -1,578 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use std::path::Path;
-use std::path::PathBuf;
-use std::sync::Arc;
-
-use deno_ast::ModuleSpecifier;
-use deno_ast::TextChange;
-use deno_core::anyhow::bail;
-use deno_core::anyhow::Context;
-use deno_core::error::AnyError;
-use deno_core::futures::FutureExt;
-use deno_core::resolve_url_or_path;
-use deno_graph::GraphKind;
-use deno_runtime::colors;
-use log::warn;
-
-use crate::args::CliOptions;
-use crate::args::ConfigFile;
-use crate::args::Flags;
-use crate::args::FmtOptionsConfig;
-use crate::args::VendorFlags;
-use crate::factory::CliFactory;
-use crate::tools::fmt::format_json;
-use crate::util::fs::canonicalize_path;
-use crate::util::fs::resolve_from_cwd;
-use crate::util::path::relative_specifier;
-use deno_runtime::fs_util::specifier_to_file_path;
-
-mod analyze;
-mod build;
-mod import_map;
-mod mappings;
-mod specifiers;
-#[cfg(test)]
-mod test;
-
-pub async fn vendor(
- flags: Arc<Flags>,
- vendor_flags: VendorFlags,
-) -> Result<(), AnyError> {
- log::info!(
- "{}",
- colors::yellow("⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.\nAdd `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead."),
- );
- let mut cli_options = CliOptions::from_flags(flags)?;
- let raw_output_dir = match &vendor_flags.output_path {
- Some(output_path) => PathBuf::from(output_path).to_owned(),
- None => PathBuf::from("vendor/"),
- };
- let output_dir = resolve_from_cwd(&raw_output_dir)?;
- validate_output_dir(&output_dir, &vendor_flags)?;
- validate_options(&mut cli_options, &output_dir)?;
- let factory = CliFactory::from_cli_options(Arc::new(cli_options));
- let cli_options = factory.cli_options()?;
- if cli_options.workspace().config_folders().len() > 1 {
- bail!("deno vendor is not supported in a workspace. Set `\"vendor\": true` in the workspace deno.json file instead");
- }
- let entry_points =
- resolve_entry_points(&vendor_flags, cli_options.initial_cwd())?;
- let jsx_import_source = cli_options
- .workspace()
- .to_maybe_jsx_import_source_config()?;
- let module_graph_creator = factory.module_graph_creator().await?.clone();
- let workspace_resolver = factory.workspace_resolver().await?;
- let root_folder = cli_options.workspace().root_folder_configs();
- let maybe_config_file = root_folder.deno_json.as_ref();
- let output = build::build(build::BuildInput {
- entry_points,
- build_graph: move |entry_points| {
- async move {
- module_graph_creator
- .create_graph(GraphKind::All, entry_points)
- .await
- }
- .boxed_local()
- },
- parsed_source_cache: factory.parsed_source_cache(),
- output_dir: &output_dir,
- maybe_original_import_map: workspace_resolver.maybe_import_map(),
- maybe_jsx_import_source: jsx_import_source.as_ref(),
- resolver: factory.resolver().await?.as_graph_resolver(),
- environment: &build::RealVendorEnvironment,
- })
- .await?;
-
- let vendored_count = output.vendored_count;
- let graph = output.graph;
- let npm_package_count = graph.npm_packages.len();
- let try_add_node_modules_dir = npm_package_count > 0
- && cli_options
- .node_modules_dir()?
- .map(|m| m.uses_node_modules_dir())
- .unwrap_or(true);
-
- log::info!(
- concat!("Vendored {} {} into {} directory.",),
- vendored_count,
- if vendored_count == 1 {
- "module"
- } else {
- "modules"
- },
- raw_output_dir.display(),
- );
-
- let try_add_import_map = vendored_count > 0;
- let modified_result = maybe_update_config_file(
- &output_dir,
- maybe_config_file,
- try_add_import_map,
- try_add_node_modules_dir,
- );
-
- // cache the node_modules folder when it's been added to the config file
- if modified_result.added_node_modules_dir {
- let node_modules_path =
- cli_options.node_modules_dir_path().cloned().or_else(|| {
- maybe_config_file
- .as_ref()
- .map(|d| &d.specifier)
- .filter(|c| c.scheme() == "file")
- .and_then(|c| c.to_file_path().ok())
- .map(|config_path| config_path.parent().unwrap().join("node_modules"))
- });
- if let Some(node_modules_path) = node_modules_path {
- let cli_options =
- cli_options.with_node_modules_dir_path(node_modules_path);
- let factory = CliFactory::from_cli_options(Arc::new(cli_options));
- if let Some(managed) = factory.npm_resolver().await?.as_managed() {
- managed.cache_packages().await?;
- }
- }
- log::info!(
- concat!(
- "Vendored {} npm {} into node_modules directory. Set `nodeModulesDir: false` ",
- "in the Deno configuration file to disable vendoring npm packages in the future.",
- ),
- npm_package_count,
- if npm_package_count == 1 {
- "package"
- } else {
- "packages"
- },
- );
- }
-
- if vendored_count > 0 {
- let import_map_path = raw_output_dir.join("import_map.json");
- if modified_result.updated_import_map {
- log::info!(
- concat!(
- "\nUpdated your local Deno configuration file with a reference to the ",
- "new vendored import map at {}. Invoking Deno subcommands will now ",
- "automatically resolve using the vendored modules. You may override ",
- "this by providing the `--import-map <other-import-map>` flag or by ",
- "manually editing your Deno configuration file.",
- ),
- import_map_path.display(),
- );
- } else {
- log::info!(
- concat!(
- "\nTo use vendored modules, specify the `--import-map {}` flag when ",
- r#"invoking Deno subcommands or add an `"importMap": "<path_to_vendored_import_map>"` "#,
- "entry to a deno.json file.",
- ),
- import_map_path.display(),
- );
- }
- }
-
- Ok(())
-}
-
-fn validate_output_dir(
- output_dir: &Path,
- flags: &VendorFlags,
-) -> Result<(), AnyError> {
- if !flags.force && !is_dir_empty(output_dir)? {
- bail!(concat!(
- "Output directory was not empty. Please specify an empty directory or use ",
- "--force to ignore this error and potentially overwrite its contents.",
- ));
- }
- Ok(())
-}
-
-fn validate_options(
- options: &mut CliOptions,
- output_dir: &Path,
-) -> Result<(), AnyError> {
- let import_map_specifier = options
- .resolve_specified_import_map_specifier()?
- .or_else(|| {
- let config_file = options.workspace().root_deno_json()?;
- config_file
- .to_import_map_specifier()
- .ok()
- .flatten()
- .or_else(|| {
- if config_file.is_an_import_map() {
- Some(config_file.specifier.clone())
- } else {
- None
- }
- })
- });
- // check the import map
- if let Some(import_map_path) = import_map_specifier
- .and_then(|p| specifier_to_file_path(&p).ok())
- .and_then(|p| canonicalize_path(&p).ok())
- {
- // make the output directory in order to canonicalize it for the check below
- std::fs::create_dir_all(output_dir)?;
- let output_dir = canonicalize_path(output_dir).with_context(|| {
- format!("Failed to canonicalize: {}", output_dir.display())
- })?;
-
- if import_map_path.starts_with(output_dir) {
- // canonicalize to make the test for this pass on the CI
- let cwd = canonicalize_path(&std::env::current_dir()?)?;
- // We don't allow using the output directory to help generate the
- // new state because this may lead to cryptic error messages.
- log::warn!(
- concat!(
- "Ignoring import map. Specifying an import map file ({}) in the ",
- "deno vendor output directory is not supported. If you wish to use ",
- "an import map while vendoring, please specify one located outside ",
- "this directory."
- ),
- import_map_path
- .strip_prefix(&cwd)
- .unwrap_or(&import_map_path)
- .display()
- .to_string(),
- );
-
- // don't use an import map in the config
- options.set_import_map_specifier(None);
- }
- }
-
- Ok(())
-}
-
-fn maybe_update_config_file(
- output_dir: &Path,
- maybe_config_file: Option<&Arc<ConfigFile>>,
- try_add_import_map: bool,
- try_add_node_modules_dir: bool,
-) -> ModifiedResult {
- assert!(output_dir.is_absolute());
- let config_file = match maybe_config_file {
- Some(config_file) => config_file,
- None => return ModifiedResult::default(),
- };
- if config_file.specifier.scheme() != "file" {
- return ModifiedResult::default();
- }
-
- let fmt_config_options = config_file
- .to_fmt_config()
- .ok()
- .map(|config| config.options)
- .unwrap_or_default();
- let result = update_config_file(
- config_file,
- &fmt_config_options,
- if try_add_import_map {
- Some(
- ModuleSpecifier::from_file_path(output_dir.join("import_map.json"))
- .unwrap(),
- )
- } else {
- None
- },
- try_add_node_modules_dir,
- );
- match result {
- Ok(modified_result) => modified_result,
- Err(err) => {
- warn!("Error updating config file. {:#}", err);
- ModifiedResult::default()
- }
- }
-}
-
-fn update_config_file(
- config_file: &ConfigFile,
- fmt_options: &FmtOptionsConfig,
- import_map_specifier: Option<ModuleSpecifier>,
- try_add_node_modules_dir: bool,
-) -> Result<ModifiedResult, AnyError> {
- let config_path = specifier_to_file_path(&config_file.specifier)?;
- let config_text = std::fs::read_to_string(&config_path)?;
- let import_map_specifier =
- import_map_specifier.and_then(|import_map_specifier| {
- relative_specifier(&config_file.specifier, &import_map_specifier)
- });
- let modified_result = update_config_text(
- &config_text,
- fmt_options,
- import_map_specifier.as_deref(),
- try_add_node_modules_dir,
- )?;
- if let Some(new_text) = &modified_result.new_text {
- std::fs::write(config_path, new_text)?;
- }
- Ok(modified_result)
-}
-
-#[derive(Default)]
-struct ModifiedResult {
- updated_import_map: bool,
- added_node_modules_dir: bool,
- new_text: Option<String>,
-}
-
-fn update_config_text(
- text: &str,
- fmt_options: &FmtOptionsConfig,
- import_map_specifier: Option<&str>,
- try_add_node_modules_dir: bool,
-) -> Result<ModifiedResult, AnyError> {
- use jsonc_parser::ast::ObjectProp;
- use jsonc_parser::ast::Value;
- let text = if text.trim().is_empty() { "{}\n" } else { text };
- let ast =
- jsonc_parser::parse_to_ast(text, &Default::default(), &Default::default())?;
- let obj = match ast.value {
- Some(Value::Object(obj)) => obj,
- _ => bail!("Failed updating config file due to no object."),
- };
- let mut modified_result = ModifiedResult::default();
- let mut text_changes = Vec::new();
- let mut should_format = false;
-
- if try_add_node_modules_dir {
- // Only modify the nodeModulesDir property if it's not set
- // as this allows people to opt-out of this when vendoring
- // by specifying `nodeModulesDir: false`
- if obj.get("nodeModulesDir").is_none() {
- let insert_position = obj.range.end - 1;
- text_changes.push(TextChange {
- range: insert_position..insert_position,
- new_text: r#""nodeModulesDir": "auto""#.to_string(),
- });
- should_format = true;
- modified_result.added_node_modules_dir = true;
- }
- }
-
- if let Some(import_map_specifier) = import_map_specifier {
- let import_map_specifier = import_map_specifier.replace('\"', "\\\"");
- match obj.get("importMap") {
- Some(ObjectProp {
- value: Value::StringLit(lit),
- ..
- }) => {
- text_changes.push(TextChange {
- range: lit.range.start..lit.range.end,
- new_text: format!("\"{}\"", import_map_specifier),
- });
- modified_result.updated_import_map = true;
- }
- None => {
- // insert it crudely at a position that won't cause any issues
- // with comments and format after to make it look nice
- let insert_position = obj.range.end - 1;
- text_changes.push(TextChange {
- range: insert_position..insert_position,
- new_text: format!(r#""importMap": "{}""#, import_map_specifier),
- });
- should_format = true;
- modified_result.updated_import_map = true;
- }
- // shouldn't happen
- Some(_) => {
- bail!("Failed updating importMap in config file due to invalid type.")
- }
- }
- }
-
- if text_changes.is_empty() {
- return Ok(modified_result);
- }
-
- let new_text = deno_ast::apply_text_changes(text, text_changes);
- modified_result.new_text = if should_format {
- format_json(&PathBuf::from("deno.json"), &new_text, fmt_options)
- .ok()
- .map(|formatted_text| formatted_text.unwrap_or(new_text))
- } else {
- Some(new_text)
- };
- Ok(modified_result)
-}
-
-fn is_dir_empty(dir_path: &Path) -> Result<bool, AnyError> {
- match std::fs::read_dir(dir_path) {
- Ok(mut dir) => Ok(dir.next().is_none()),
- Err(err) if err.kind() == std::io::ErrorKind::NotFound => Ok(true),
- Err(err) => {
- bail!("Error reading directory {}: {}", dir_path.display(), err)
- }
- }
-}
-
-fn resolve_entry_points(
- flags: &VendorFlags,
- initial_cwd: &Path,
-) -> Result<Vec<ModuleSpecifier>, AnyError> {
- flags
- .specifiers
- .iter()
- .map(|p| resolve_url_or_path(p, initial_cwd).map_err(|e| e.into()))
- .collect::<Result<Vec<_>, _>>()
-}
-
-#[cfg(test)]
-mod internal_test {
- use super::*;
- use pretty_assertions::assert_eq;
-
- #[test]
- fn update_config_text_no_existing_props_add_prop() {
- let result = update_config_text(
- "{\n}",
- &Default::default(),
- Some("./vendor/import_map.json"),
- false,
- )
- .unwrap();
- assert!(result.updated_import_map);
- assert!(!result.added_node_modules_dir);
- assert_eq!(
- result.new_text.unwrap(),
- r#"{
- "importMap": "./vendor/import_map.json"
-}
-"#
- );
-
- let result = update_config_text(
- "{\n}",
- &Default::default(),
- Some("./vendor/import_map.json"),
- true,
- )
- .unwrap();
- assert!(result.updated_import_map);
- assert!(result.added_node_modules_dir);
- assert_eq!(
- result.new_text.unwrap(),
- r#"{
- "nodeModulesDir": "auto",
- "importMap": "./vendor/import_map.json"
-}
-"#
- );
-
- let result =
- update_config_text("{\n}", &Default::default(), None, true).unwrap();
- assert!(!result.updated_import_map);
- assert!(result.added_node_modules_dir);
- assert_eq!(
- result.new_text.unwrap(),
- r#"{
- "nodeModulesDir": "auto"
-}
-"#
- );
- }
-
- #[test]
- fn update_config_text_existing_props_add_prop() {
- let result = update_config_text(
- r#"{
- "tasks": {
- "task1": "other"
- }
-}
-"#,
- &Default::default(),
- Some("./vendor/import_map.json"),
- false,
- )
- .unwrap();
- assert_eq!(
- result.new_text.unwrap(),
- r#"{
- "tasks": {
- "task1": "other"
- },
- "importMap": "./vendor/import_map.json"
-}
-"#
- );
-
- // trailing comma
- let result = update_config_text(
- r#"{
- "tasks": {
- "task1": "other"
- },
-}
-"#,
- &Default::default(),
- Some("./vendor/import_map.json"),
- false,
- )
- .unwrap();
- assert_eq!(
- result.new_text.unwrap(),
- r#"{
- "tasks": {
- "task1": "other"
- },
- "importMap": "./vendor/import_map.json"
-}
-"#
- );
- }
-
- #[test]
- fn update_config_text_update_prop() {
- let result = update_config_text(
- r#"{
- "importMap": "./local.json"
-}
-"#,
- &Default::default(),
- Some("./vendor/import_map.json"),
- false,
- )
- .unwrap();
- assert_eq!(
- result.new_text.unwrap(),
- r#"{
- "importMap": "./vendor/import_map.json"
-}
-"#
- );
- }
-
- #[test]
- fn no_update_node_modules_dir() {
- // will not update if this is already set (even if it's "none")
- let result = update_config_text(
- r#"{
- "nodeModulesDir": "none"
-}
-"#,
- &Default::default(),
- None,
- true,
- )
- .unwrap();
- assert!(!result.added_node_modules_dir);
- assert!(!result.updated_import_map);
- assert_eq!(result.new_text, None);
-
- let result = update_config_text(
- r#"{
- "nodeModulesDir": "auto"
-}
-"#,
- &Default::default(),
- None,
- true,
- )
- .unwrap();
- assert!(!result.added_node_modules_dir);
- assert!(!result.updated_import_map);
- assert_eq!(result.new_text, None);
- }
-}
diff --git a/cli/tools/vendor/specifiers.rs b/cli/tools/vendor/specifiers.rs
deleted file mode 100644
index e0e0f5337..000000000
--- a/cli/tools/vendor/specifiers.rs
+++ /dev/null
@@ -1,208 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use std::collections::BTreeMap;
-use std::collections::HashSet;
-use std::path::PathBuf;
-
-use deno_ast::ModuleSpecifier;
-use deno_core::anyhow::anyhow;
-use deno_core::error::AnyError;
-
-use crate::util::path::is_banned_path_char;
-use crate::util::path::path_with_stem_suffix;
-use crate::util::path::root_url_to_safe_local_dirname;
-
-/// Partitions the provided specifiers by the non-path and non-query parts of a specifier.
-pub fn partition_by_root_specifiers<'a>(
- specifiers: impl Iterator<Item = &'a ModuleSpecifier>,
-) -> BTreeMap<ModuleSpecifier, Vec<ModuleSpecifier>> {
- let mut root_specifiers: BTreeMap<ModuleSpecifier, Vec<ModuleSpecifier>> =
- Default::default();
- for remote_specifier in specifiers {
- let mut root_specifier = remote_specifier.clone();
- root_specifier.set_query(None);
- root_specifier.set_path("/");
-
- let specifiers = root_specifiers.entry(root_specifier).or_default();
- specifiers.push(remote_specifier.clone());
- }
- root_specifiers
-}
-
-/// Gets the directory name to use for the provided root.
-pub fn dir_name_for_root(root: &ModuleSpecifier) -> PathBuf {
- root_url_to_safe_local_dirname(root)
-}
-
-/// Gets a unique file path given the provided file path
-/// and the set of existing file paths. Inserts to the
-/// set when finding a unique path.
-pub fn get_unique_path(
- mut path: PathBuf,
- unique_set: &mut HashSet<String>,
-) -> PathBuf {
- let original_path = path.clone();
- let mut count = 2;
- // case insensitive comparison so the output works on case insensitive file systems
- while !unique_set.insert(path.to_string_lossy().to_lowercase()) {
- path = path_with_stem_suffix(&original_path, &format!("_{count}"));
- count += 1;
- }
- path
-}
-
-pub fn make_url_relative(
- root: &ModuleSpecifier,
- url: &ModuleSpecifier,
-) -> Result<String, AnyError> {
- root.make_relative(url).ok_or_else(|| {
- anyhow!(
- "Error making url ({}) relative to root: {}",
- url.to_string(),
- root.to_string()
- )
- })
-}
-
-pub fn is_remote_specifier(specifier: &ModuleSpecifier) -> bool {
- matches!(specifier.scheme().to_lowercase().as_str(), "http" | "https")
-}
-
-pub fn is_remote_specifier_text(text: &str) -> bool {
- let text = text.trim_start().to_lowercase();
- text.starts_with("http:") || text.starts_with("https:")
-}
-
-pub fn sanitize_filepath(text: &str) -> String {
- text
- .chars()
- .map(|c| if is_banned_path_char(c) { '_' } else { c })
- .collect()
-}
-
-#[cfg(test)]
-mod test {
- use super::*;
- use pretty_assertions::assert_eq;
-
- #[test]
- fn partition_by_root_specifiers_same_sub_folder() {
- run_partition_by_root_specifiers_test(
- vec![
- "https://deno.land/x/mod/A.ts",
- "https://deno.land/x/mod/other/A.ts",
- ],
- vec![(
- "https://deno.land/",
- vec![
- "https://deno.land/x/mod/A.ts",
- "https://deno.land/x/mod/other/A.ts",
- ],
- )],
- );
- }
-
- #[test]
- fn partition_by_root_specifiers_different_sub_folder() {
- run_partition_by_root_specifiers_test(
- vec![
- "https://deno.land/x/mod/A.ts",
- "https://deno.land/x/other/A.ts",
- ],
- vec![(
- "https://deno.land/",
- vec![
- "https://deno.land/x/mod/A.ts",
- "https://deno.land/x/other/A.ts",
- ],
- )],
- );
- }
-
- #[test]
- fn partition_by_root_specifiers_different_hosts() {
- run_partition_by_root_specifiers_test(
- vec![
- "https://deno.land/mod/A.ts",
- "http://deno.land/B.ts",
- "https://deno.land:8080/C.ts",
- "https://localhost/mod/A.ts",
- "https://other/A.ts",
- ],
- vec![
- ("http://deno.land/", vec!["http://deno.land/B.ts"]),
- ("https://deno.land/", vec!["https://deno.land/mod/A.ts"]),
- (
- "https://deno.land:8080/",
- vec!["https://deno.land:8080/C.ts"],
- ),
- ("https://localhost/", vec!["https://localhost/mod/A.ts"]),
- ("https://other/", vec!["https://other/A.ts"]),
- ],
- );
- }
-
- fn run_partition_by_root_specifiers_test(
- input: Vec<&str>,
- expected: Vec<(&str, Vec<&str>)>,
- ) {
- let input = input
- .iter()
- .map(|s| ModuleSpecifier::parse(s).unwrap())
- .collect::<Vec<_>>();
- let output = partition_by_root_specifiers(input.iter());
- // the assertion is much easier to compare when everything is strings
- let output = output
- .into_iter()
- .map(|(s, vec)| {
- (
- s.to_string(),
- vec.into_iter().map(|s| s.to_string()).collect::<Vec<_>>(),
- )
- })
- .collect::<Vec<_>>();
- let expected = expected
- .into_iter()
- .map(|(s, vec)| {
- (
- s.to_string(),
- vec.into_iter().map(|s| s.to_string()).collect::<Vec<_>>(),
- )
- })
- .collect::<Vec<_>>();
- assert_eq!(output, expected);
- }
-
- #[test]
- fn test_unique_path() {
- let mut paths = HashSet::new();
- assert_eq!(
- get_unique_path(PathBuf::from("/test"), &mut paths),
- PathBuf::from("/test")
- );
- assert_eq!(
- get_unique_path(PathBuf::from("/test"), &mut paths),
- PathBuf::from("/test_2")
- );
- assert_eq!(
- get_unique_path(PathBuf::from("/test"), &mut paths),
- PathBuf::from("/test_3")
- );
- assert_eq!(
- get_unique_path(PathBuf::from("/TEST"), &mut paths),
- PathBuf::from("/TEST_4")
- );
- assert_eq!(
- get_unique_path(PathBuf::from("/test.txt"), &mut paths),
- PathBuf::from("/test.txt")
- );
- assert_eq!(
- get_unique_path(PathBuf::from("/test.txt"), &mut paths),
- PathBuf::from("/test_2.txt")
- );
- assert_eq!(
- get_unique_path(PathBuf::from("/TEST.TXT"), &mut paths),
- PathBuf::from("/TEST_3.TXT")
- );
- }
-}
diff --git a/cli/tools/vendor/test.rs b/cli/tools/vendor/test.rs
deleted file mode 100644
index 65f37efdc..000000000
--- a/cli/tools/vendor/test.rs
+++ /dev/null
@@ -1,357 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use std::cell::RefCell;
-use std::collections::HashMap;
-use std::collections::HashSet;
-use std::path::Path;
-use std::path::PathBuf;
-use std::sync::Arc;
-
-use deno_ast::ModuleSpecifier;
-use deno_config::workspace::WorkspaceResolver;
-use deno_core::anyhow::anyhow;
-use deno_core::anyhow::bail;
-use deno_core::error::AnyError;
-use deno_core::futures;
-use deno_core::futures::FutureExt;
-use deno_core::serde_json;
-use deno_graph::source::LoadFuture;
-use deno_graph::source::LoadResponse;
-use deno_graph::source::Loader;
-use deno_graph::DefaultModuleAnalyzer;
-use deno_graph::GraphKind;
-use deno_graph::ModuleGraph;
-use import_map::ImportMap;
-
-use crate::args::JsxImportSourceConfig;
-use crate::cache::ParsedSourceCache;
-use crate::resolver::CliGraphResolver;
-use crate::resolver::CliGraphResolverOptions;
-
-use super::build::VendorEnvironment;
-
-// Utilities that help `deno vendor` get tested in memory.
-
-type RemoteFileText = String;
-type RemoteFileHeaders = Option<HashMap<String, String>>;
-type RemoteFileResult = Result<(RemoteFileText, RemoteFileHeaders), String>;
-
-#[derive(Clone, Default)]
-pub struct TestLoader {
- files: HashMap<ModuleSpecifier, RemoteFileResult>,
- redirects: HashMap<ModuleSpecifier, ModuleSpecifier>,
-}
-
-impl TestLoader {
- pub fn add(
- &mut self,
- path_or_specifier: impl AsRef<str>,
- text: impl AsRef<str>,
- ) -> &mut Self {
- self.add_result(path_or_specifier, Ok((text.as_ref().to_string(), None)))
- }
-
- pub fn add_failure(
- &mut self,
- path_or_specifier: impl AsRef<str>,
- message: impl AsRef<str>,
- ) -> &mut Self {
- self.add_result(path_or_specifier, Err(message.as_ref().to_string()))
- }
-
- fn add_result(
- &mut self,
- path_or_specifier: impl AsRef<str>,
- result: RemoteFileResult,
- ) -> &mut Self {
- if path_or_specifier
- .as_ref()
- .to_lowercase()
- .starts_with("http")
- {
- self.files.insert(
- ModuleSpecifier::parse(path_or_specifier.as_ref()).unwrap(),
- result,
- );
- } else {
- let path = make_path(path_or_specifier.as_ref());
- let specifier = ModuleSpecifier::from_file_path(path).unwrap();
- self.files.insert(specifier, result);
- }
- self
- }
-
- pub fn add_with_headers(
- &mut self,
- specifier: impl AsRef<str>,
- text: impl AsRef<str>,
- headers: &[(&str, &str)],
- ) -> &mut Self {
- let headers = headers
- .iter()
- .map(|(key, value)| (key.to_string(), value.to_string()))
- .collect();
- self.files.insert(
- ModuleSpecifier::parse(specifier.as_ref()).unwrap(),
- Ok((text.as_ref().to_string(), Some(headers))),
- );
- self
- }
-
- pub fn add_redirect(
- &mut self,
- from: impl AsRef<str>,
- to: impl AsRef<str>,
- ) -> &mut Self {
- self.redirects.insert(
- ModuleSpecifier::parse(from.as_ref()).unwrap(),
- ModuleSpecifier::parse(to.as_ref()).unwrap(),
- );
- self
- }
-}
-
-impl Loader for TestLoader {
- fn load(
- &self,
- specifier: &ModuleSpecifier,
- _options: deno_graph::source::LoadOptions,
- ) -> LoadFuture {
- if let Some(redirect) = self.redirects.get(specifier) {
- return Box::pin(futures::future::ready(Ok(Some(
- LoadResponse::Redirect {
- specifier: redirect.clone(),
- },
- ))));
- }
- let result = self.files.get(specifier).map(|result| match result {
- Ok(result) => Ok(LoadResponse::Module {
- specifier: specifier.clone(),
- content: result.0.clone().into_bytes().into(),
- maybe_headers: result.1.clone(),
- }),
- Err(err) => Err(err),
- });
- let result = match result {
- Some(Ok(result)) => Ok(Some(result)),
- Some(Err(err)) => Err(anyhow!("{}", err)),
- None if specifier.scheme() == "data" => {
- deno_graph::source::load_data_url(specifier)
- }
- None => Ok(None),
- };
- Box::pin(futures::future::ready(result))
- }
-}
-
-#[derive(Default)]
-struct TestVendorEnvironment {
- directories: RefCell<HashSet<PathBuf>>,
- files: RefCell<HashMap<PathBuf, String>>,
-}
-
-impl VendorEnvironment for TestVendorEnvironment {
- fn create_dir_all(&self, dir_path: &Path) -> Result<(), AnyError> {
- let mut directories = self.directories.borrow_mut();
- for path in dir_path.ancestors() {
- if !directories.insert(path.to_path_buf()) {
- break;
- }
- }
- Ok(())
- }
-
- fn write_file(&self, file_path: &Path, text: &[u8]) -> Result<(), AnyError> {
- let parent = file_path.parent().unwrap();
- if !self.directories.borrow().contains(parent) {
- bail!("Directory not found: {}", parent.display());
- }
- self.files.borrow_mut().insert(
- file_path.to_path_buf(),
- String::from_utf8(text.to_vec()).unwrap(),
- );
- Ok(())
- }
-}
-
-pub struct VendorOutput {
- pub files: Vec<(String, String)>,
- pub import_map: Option<serde_json::Value>,
-}
-
-#[derive(Default)]
-pub struct VendorTestBuilder {
- entry_points: Vec<ModuleSpecifier>,
- loader: TestLoader,
- maybe_original_import_map: Option<ImportMap>,
- environment: TestVendorEnvironment,
- jsx_import_source_config: Option<JsxImportSourceConfig>,
-}
-
-impl VendorTestBuilder {
- pub fn with_default_setup() -> Self {
- let mut builder = VendorTestBuilder::default();
- builder.add_entry_point("/mod.ts");
- builder
- }
-
- pub fn resolve_to_url(&self, path: &str) -> ModuleSpecifier {
- ModuleSpecifier::from_file_path(make_path(path)).unwrap()
- }
-
- pub fn new_import_map(&self, base_path: &str) -> ImportMap {
- let base = self.resolve_to_url(base_path);
- ImportMap::new(base)
- }
-
- pub fn set_original_import_map(
- &mut self,
- import_map: ImportMap,
- ) -> &mut Self {
- self.maybe_original_import_map = Some(import_map);
- self
- }
-
- pub fn add_entry_point(&mut self, entry_point: impl AsRef<str>) -> &mut Self {
- let entry_point = make_path(entry_point.as_ref());
- self
- .entry_points
- .push(ModuleSpecifier::from_file_path(entry_point).unwrap());
- self
- }
-
- pub fn set_jsx_import_source_config(
- &mut self,
- jsx_import_source_config: JsxImportSourceConfig,
- ) -> &mut Self {
- self.jsx_import_source_config = Some(jsx_import_source_config);
- self
- }
-
- pub async fn build(&mut self) -> Result<VendorOutput, AnyError> {
- let output_dir = make_path("/vendor");
- let entry_points = self.entry_points.clone();
- let loader = self.loader.clone();
- let parsed_source_cache = ParsedSourceCache::default();
- let resolver = Arc::new(build_resolver(
- output_dir.parent().unwrap(),
- self.jsx_import_source_config.clone(),
- self.maybe_original_import_map.clone(),
- ));
- super::build::build(super::build::BuildInput {
- entry_points,
- build_graph: {
- let resolver = resolver.clone();
- move |entry_points| {
- async move {
- Ok(
- build_test_graph(
- entry_points,
- loader,
- resolver.as_graph_resolver(),
- &DefaultModuleAnalyzer,
- )
- .await,
- )
- }
- .boxed_local()
- }
- },
- parsed_source_cache: &parsed_source_cache,
- output_dir: &output_dir,
- maybe_original_import_map: self.maybe_original_import_map.as_ref(),
- maybe_jsx_import_source: self.jsx_import_source_config.as_ref(),
- resolver: resolver.as_graph_resolver(),
- environment: &self.environment,
- })
- .await?;
-
- let mut files = self.environment.files.borrow_mut();
- let import_map = files.remove(&output_dir.join("import_map.json"));
- let mut files = files
- .iter()
- .map(|(path, text)| (path_to_string(path), text.to_string()))
- .collect::<Vec<_>>();
-
- files.sort_by(|a, b| a.0.cmp(&b.0));
-
- Ok(VendorOutput {
- import_map: import_map.map(|text| serde_json::from_str(&text).unwrap()),
- files,
- })
- }
-
- pub fn with_loader(&mut self, action: impl Fn(&mut TestLoader)) -> &mut Self {
- action(&mut self.loader);
- self
- }
-}
-
-fn build_resolver(
- root_dir: &Path,
- maybe_jsx_import_source_config: Option<JsxImportSourceConfig>,
- maybe_original_import_map: Option<ImportMap>,
-) -> CliGraphResolver {
- CliGraphResolver::new(CliGraphResolverOptions {
- node_resolver: None,
- npm_resolver: None,
- sloppy_imports_resolver: None,
- workspace_resolver: Arc::new(WorkspaceResolver::new_raw(
- Arc::new(ModuleSpecifier::from_directory_path(root_dir).unwrap()),
- maybe_original_import_map,
- Vec::new(),
- Vec::new(),
- deno_config::workspace::PackageJsonDepResolution::Enabled,
- )),
- maybe_jsx_import_source_config,
- maybe_vendor_dir: None,
- bare_node_builtins_enabled: false,
- })
-}
-
-async fn build_test_graph(
- roots: Vec<ModuleSpecifier>,
- loader: TestLoader,
- resolver: &dyn deno_graph::source::Resolver,
- analyzer: &dyn deno_graph::ModuleAnalyzer,
-) -> ModuleGraph {
- let mut graph = ModuleGraph::new(GraphKind::All);
- graph
- .build(
- roots,
- &loader,
- deno_graph::BuildOptions {
- resolver: Some(resolver),
- module_analyzer: analyzer,
- ..Default::default()
- },
- )
- .await;
- graph
-}
-
-fn make_path(text: &str) -> PathBuf {
- // This should work all in memory. We're waiting on
- // https://github.com/servo/rust-url/issues/730 to provide
- // a cross platform path here
- assert!(text.starts_with('/'));
- if cfg!(windows) {
- PathBuf::from(format!("C:{}", text.replace('/', "\\")))
- } else {
- PathBuf::from(text)
- }
-}
-
-fn path_to_string<P>(path: P) -> String
-where
- P: AsRef<Path>,
-{
- let path = path.as_ref();
- // inverse of the function above
- let path = path.to_string_lossy();
- if cfg!(windows) {
- path.replace("C:\\", "\\").replace('\\', "/")
- } else {
- path.to_string()
- }
-}
diff --git a/cli/util/fs.rs b/cli/util/fs.rs
index 145f9c83b..d723d24e1 100644
--- a/cli/util/fs.rs
+++ b/cli/util/fs.rs
@@ -1,6 +1,5 @@
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-use std::env::current_dir;
use std::fs::OpenOptions;
use std::io::Error;
use std::io::ErrorKind;
@@ -18,7 +17,6 @@ use deno_config::glob::WalkEntry;
use deno_core::anyhow::anyhow;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
-pub use deno_core::normalize_path;
use deno_core::unsync::spawn_blocking;
use deno_core::ModuleSpecifier;
use deno_runtime::deno_fs::FileSystem;
@@ -255,18 +253,6 @@ fn canonicalize_path_maybe_not_exists_with_custom_fn(
}
}
-pub fn resolve_from_cwd(path: &Path) -> Result<PathBuf, AnyError> {
- let resolved_path = if path.is_absolute() {
- path.to_owned()
- } else {
- let cwd =
- current_dir().context("Failed to get current working directory")?;
- cwd.join(path)
- };
-
- Ok(normalize_path(resolved_path))
-}
-
/// Collects module specifiers that satisfy the given predicate as a file path, by recursively walking `include`.
/// Specifiers that start with http and https are left intact.
/// Note: This ignores all .git and node_modules folders.
@@ -715,6 +701,7 @@ pub fn specifier_from_file_path(
mod tests {
use super::*;
use deno_core::futures;
+ use deno_core::normalize_path;
use deno_core::parking_lot::Mutex;
use pretty_assertions::assert_eq;
use test_util::PathRef;
@@ -722,24 +709,6 @@ mod tests {
use tokio::sync::Notify;
#[test]
- fn resolve_from_cwd_child() {
- let cwd = current_dir().unwrap();
- assert_eq!(resolve_from_cwd(Path::new("a")).unwrap(), cwd.join("a"));
- }
-
- #[test]
- fn resolve_from_cwd_dot() {
- let cwd = current_dir().unwrap();
- assert_eq!(resolve_from_cwd(Path::new(".")).unwrap(), cwd);
- }
-
- #[test]
- fn resolve_from_cwd_parent() {
- let cwd = current_dir().unwrap();
- assert_eq!(resolve_from_cwd(Path::new("a/..")).unwrap(), cwd);
- }
-
- #[test]
fn test_normalize_path() {
assert_eq!(normalize_path(Path::new("a/../b")), PathBuf::from("b"));
assert_eq!(normalize_path(Path::new("a/./b/")), PathBuf::from("a/b/"));
@@ -757,14 +726,6 @@ mod tests {
}
#[test]
- fn resolve_from_cwd_absolute() {
- let expected = Path::new("a");
- let cwd = current_dir().unwrap();
- let absolute_expected = cwd.join(expected);
- assert_eq!(resolve_from_cwd(expected).unwrap(), absolute_expected);
- }
-
- #[test]
fn test_collect_specifiers() {
fn create_files(dir_path: &PathRef, files: &[&str]) {
dir_path.create_dir_all();
diff --git a/cli/util/path.rs b/cli/util/path.rs
index 16378e30b..804b26f65 100644
--- a/cli/util/path.rs
+++ b/cli/util/path.rs
@@ -145,34 +145,6 @@ pub fn relative_specifier(
Some(to_percent_decoded_str(&text))
}
-/// Gets a path with the specified file stem suffix.
-///
-/// Ex. `file.ts` with suffix `_2` returns `file_2.ts`
-pub fn path_with_stem_suffix(path: &Path, suffix: &str) -> PathBuf {
- if let Some(file_name) = path.file_name().map(|f| f.to_string_lossy()) {
- if let Some(file_stem) = path.file_stem().map(|f| f.to_string_lossy()) {
- if let Some(ext) = path.extension().map(|f| f.to_string_lossy()) {
- return if file_stem.to_lowercase().ends_with(".d") {
- path.with_file_name(format!(
- "{}{}.{}.{}",
- &file_stem[..file_stem.len() - ".d".len()],
- suffix,
- // maintain casing
- &file_stem[file_stem.len() - "d".len()..],
- ext
- ))
- } else {
- path.with_file_name(format!("{file_stem}{suffix}.{ext}"))
- };
- }
- }
-
- path.with_file_name(format!("{file_name}{suffix}"))
- } else {
- path.with_file_name(suffix)
- }
-}
-
#[cfg_attr(windows, allow(dead_code))]
pub fn relative_path(from: &Path, to: &Path) -> Option<PathBuf> {
pathdiff::diff_paths(to, from)
@@ -406,46 +378,6 @@ mod test {
}
#[test]
- fn test_path_with_stem_suffix() {
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/"), "_2"),
- PathBuf::from("/_2")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test"), "_2"),
- PathBuf::from("/test_2")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test.txt"), "_2"),
- PathBuf::from("/test_2.txt")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test/subdir"), "_2"),
- PathBuf::from("/test/subdir_2")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test/subdir.other.txt"), "_2"),
- PathBuf::from("/test/subdir.other_2.txt")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test.d.ts"), "_2"),
- PathBuf::from("/test_2.d.ts")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test.D.TS"), "_2"),
- PathBuf::from("/test_2.D.TS")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test.d.mts"), "_2"),
- PathBuf::from("/test_2.d.mts")
- );
- assert_eq!(
- path_with_stem_suffix(&PathBuf::from("/test.d.cts"), "_2"),
- PathBuf::from("/test_2.d.cts")
- );
- }
-
- #[test]
fn test_to_percent_decoded_str() {
let str = to_percent_decoded_str("%F0%9F%A6%95");
assert_eq!(str, "🦕");
diff --git a/tests/integration/mod.rs b/tests/integration/mod.rs
index ea3269aaa..d12abcde6 100644
--- a/tests/integration/mod.rs
+++ b/tests/integration/mod.rs
@@ -68,8 +68,6 @@ mod task;
mod test;
#[path = "upgrade_tests.rs"]
mod upgrade;
-#[path = "vendor_tests.rs"]
-mod vendor;
#[path = "watcher_tests.rs"]
mod watcher;
#[path = "worker_tests.rs"]
diff --git a/tests/integration/vendor_tests.rs b/tests/integration/vendor_tests.rs
deleted file mode 100644
index 550fbf8b7..000000000
--- a/tests/integration/vendor_tests.rs
+++ /dev/null
@@ -1,751 +0,0 @@
-// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
-
-use deno_core::serde_json;
-use deno_core::serde_json::json;
-use pretty_assertions::assert_eq;
-use std::fmt::Write as _;
-use std::path::PathBuf;
-use test_util as util;
-use test_util::itest;
-use test_util::TempDir;
-use util::http_server;
-use util::new_deno_dir;
-use util::TestContextBuilder;
-
-const DEPRECATION_NOTICE: &str = "⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.\nAdd `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead.\n";
-
-#[test]
-fn output_dir_exists() {
- let t = TempDir::new();
- t.write("mod.ts", "");
- t.create_dir_all("vendor");
- t.write("vendor/mod.ts", "");
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("mod.ts")
- .stderr_piped()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!("{}error: Output directory was not empty. Please specify an empty directory or use --force to ignore this error and potentially overwrite its contents.", &DEPRECATION_NOTICE)
- );
- assert!(!output.status.success());
-
- // ensure it errors when using the `--output` arg too
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("--output")
- .arg("vendor")
- .arg("mod.ts")
- .stderr_piped()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!("{}error: Output directory was not empty. Please specify an empty directory or use --force to ignore this error and potentially overwrite its contents.", &DEPRECATION_NOTICE)
- );
- assert!(!output.status.success());
-
- // now use `--force`
- let status = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("mod.ts")
- .arg("--force")
- .spawn()
- .unwrap()
- .wait()
- .unwrap();
- assert!(status.success());
-}
-
-#[test]
-fn standard_test() {
- let _server = http_server();
- let t = TempDir::new();
- let vendor_dir = t.path().join("vendor2");
- t.write(
- "my_app.ts",
- "import {Logger} from 'http://localhost:4545/vendor/query_reexport.ts?testing'; new Logger().log('outputted');",
- );
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .arg("vendor")
- .arg("my_app.ts")
- .arg("--output")
- .arg("vendor2")
- .env("NO_COLOR", "1")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- concat!(
- "{}",
- "Download http://localhost:4545/vendor/query_reexport.ts?testing\n",
- "Download http://localhost:4545/vendor/logger.ts?test\n",
- "{}",
- ),
- &DEPRECATION_NOTICE,
- success_text("2 modules", "vendor2", true),
- )
- );
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
- assert!(output.status.success());
-
- assert!(vendor_dir.exists());
- assert!(!t.path().join("vendor").exists());
- let import_map: serde_json::Value =
- serde_json::from_str(&t.read_to_string("vendor2/import_map.json")).unwrap();
- assert_eq!(
- import_map,
- json!({
- "imports": {
- "http://localhost:4545/vendor/query_reexport.ts?testing": "./localhost_4545/vendor/query_reexport.ts",
- "http://localhost:4545/": "./localhost_4545/",
- },
- "scopes": {
- "./localhost_4545/": {
- "./localhost_4545/vendor/logger.ts?test": "./localhost_4545/vendor/logger.ts"
- }
- }
- }),
- );
-
- // try running the output with `--no-remote`
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("run")
- .arg("--no-remote")
- .arg("--check")
- .arg("--quiet")
- .arg("--import-map")
- .arg("vendor2/import_map.json")
- .arg("my_app.ts")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(String::from_utf8_lossy(&output.stderr).trim(), "");
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "outputted");
- assert!(output.status.success());
-}
-
-#[test]
-fn import_map_output_dir() {
- let _server = http_server();
- let t = TempDir::new();
- t.write("mod.ts", "");
- t.create_dir_all("vendor");
- t.write(
- "vendor/import_map.json",
- // will be ignored
- "{ \"imports\": { \"https://localhost:4545/\": \"./localhost/\" }}",
- );
- t.write(
- "deno.json",
- "{ \"import_map\": \"./vendor/import_map.json\" }",
- );
- t.write(
- "my_app.ts",
- "import {Logger} from 'http://localhost:4545/vendor/logger.ts'; new Logger().log('outputted');",
- );
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("--force")
- .arg("--import-map")
- .arg("vendor/import_map.json")
- .arg("my_app.ts")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- concat!(
- "{}{}\n",
- "Download http://localhost:4545/vendor/logger.ts\n",
- "{}\n\n{}",
- ),
- &DEPRECATION_NOTICE,
- ignoring_import_map_text(),
- vendored_text("1 module", "vendor/"),
- success_text_updated_deno_json("vendor/"),
- )
- );
- assert!(output.status.success());
-}
-
-#[test]
-fn remote_module_test() {
- let _server = http_server();
- let t = TempDir::new();
- let vendor_dir = t.path().join("vendor");
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("http://localhost:4545/vendor/query_reexport.ts")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- concat!(
- "{}",
- "Download http://localhost:4545/vendor/query_reexport.ts\n",
- "Download http://localhost:4545/vendor/logger.ts?test\n",
- "{}",
- ),
- &DEPRECATION_NOTICE,
- success_text("2 modules", "vendor/", true),
- )
- );
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
- assert!(output.status.success());
- assert!(vendor_dir.exists());
- assert!(vendor_dir
- .join("localhost_4545/vendor/query_reexport.ts")
- .exists());
- assert!(vendor_dir.join("localhost_4545/vendor/logger.ts").exists());
- let import_map: serde_json::Value =
- serde_json::from_str(&t.read_to_string("vendor/import_map.json")).unwrap();
- assert_eq!(
- import_map,
- json!({
- "imports": {
- "http://localhost:4545/": "./localhost_4545/",
- },
- "scopes": {
- "./localhost_4545/": {
- "./localhost_4545/vendor/logger.ts?test": "./localhost_4545/vendor/logger.ts",
- }
- }
- }),
- );
-}
-
-#[test]
-fn existing_import_map_no_remote() {
- let _server = http_server();
- let t = TempDir::new();
- t.write(
- "mod.ts",
- "import {Logger} from 'http://localhost:4545/vendor/logger.ts';",
- );
- let import_map_filename = "imports2.json";
- let import_map_text =
- r#"{ "imports": { "http://localhost:4545/vendor/": "./logger/" } }"#;
- t.write(import_map_filename, import_map_text);
- t.create_dir_all("logger");
- t.write("logger/logger.ts", "export class Logger {}");
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("mod.ts")
- .arg("--import-map")
- .arg(import_map_filename)
- .stderr_piped()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- "{}{}",
- &DEPRECATION_NOTICE,
- success_text("0 modules", "vendor/", false)
- )
- );
- assert!(output.status.success());
- // it should not have found any remote dependencies because
- // the provided import map mapped it to a local directory
- assert_eq!(t.read_to_string(import_map_filename), import_map_text);
-}
-
-#[test]
-fn existing_import_map_mixed_with_remote() {
- let _server = http_server();
- let deno_dir = new_deno_dir();
- let t = TempDir::new();
- t.write(
- "mod.ts",
- "import {Logger} from 'http://localhost:4545/vendor/logger.ts';",
- );
-
- let status = util::deno_cmd_with_deno_dir(&deno_dir)
- .current_dir(t.path())
- .arg("vendor")
- .arg("mod.ts")
- .spawn()
- .unwrap()
- .wait()
- .unwrap();
- assert!(status.success());
-
- assert_eq!(
- t.read_to_string("vendor/import_map.json"),
- r#"{
- "imports": {
- "http://localhost:4545/": "./localhost_4545/"
- }
-}
-"#,
- );
-
- // make the import map specific to support vendoring mod.ts in the next step
- t.write(
- "vendor/import_map.json",
- r#"{
- "imports": {
- "http://localhost:4545/vendor/logger.ts": "./localhost_4545/vendor/logger.ts"
- }
-}
-"#,
- );
-
- t.write(
- "mod.ts",
- concat!(
- "import {Logger} from 'http://localhost:4545/vendor/logger.ts';\n",
- "import {Logger as OtherLogger} from 'http://localhost:4545/vendor/mod.ts';\n",
- ),
- );
-
- // now vendor with the existing import map in a separate vendor directory
- let deno = util::deno_cmd_with_deno_dir(&deno_dir)
- .env("NO_COLOR", "1")
- .current_dir(t.path())
- .arg("vendor")
- .arg("mod.ts")
- .arg("--import-map")
- .arg("vendor/import_map.json")
- .arg("--output")
- .arg("vendor2")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- "{}Download http://localhost:4545/vendor/mod.ts\n{}",
- &DEPRECATION_NOTICE,
- success_text("1 module", "vendor2", true),
- )
- );
- assert!(output.status.success());
-
- // tricky scenario here where the output directory now contains a mapping
- // back to the previous vendor location
- assert_eq!(
- t.read_to_string("vendor2/import_map.json"),
- r#"{
- "imports": {
- "http://localhost:4545/vendor/logger.ts": "../vendor/localhost_4545/vendor/logger.ts",
- "http://localhost:4545/": "./localhost_4545/"
- },
- "scopes": {
- "./localhost_4545/": {
- "./localhost_4545/vendor/logger.ts": "../vendor/localhost_4545/vendor/logger.ts"
- }
- }
-}
-"#,
- );
-
- // ensure it runs
- let status = util::deno_cmd()
- .current_dir(t.path())
- .arg("run")
- .arg("--check")
- .arg("--no-remote")
- .arg("--import-map")
- .arg("vendor2/import_map.json")
- .arg("mod.ts")
- .spawn()
- .unwrap()
- .wait()
- .unwrap();
- assert!(status.success());
-}
-
-#[test]
-fn dynamic_import() {
- let _server = http_server();
- let t = TempDir::new();
- t.write(
- "mod.ts",
- "import {Logger} from 'http://localhost:4545/vendor/dynamic.ts'; new Logger().log('outputted');",
- );
-
- let status = util::deno_cmd()
- .current_dir(t.path())
- .arg("vendor")
- .arg("mod.ts")
- .spawn()
- .unwrap()
- .wait()
- .unwrap();
- assert!(status.success());
- let import_map: serde_json::Value =
- serde_json::from_str(&t.read_to_string("vendor/import_map.json")).unwrap();
- assert_eq!(
- import_map,
- json!({
- "imports": {
- "http://localhost:4545/": "./localhost_4545/",
- }
- }),
- );
-
- // try running the output with `--no-remote`
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("run")
- .arg("--allow-read=.")
- .arg("--no-remote")
- .arg("--check")
- .arg("--quiet")
- .arg("--import-map")
- .arg("vendor/import_map.json")
- .arg("mod.ts")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(String::from_utf8_lossy(&output.stderr).trim(), "");
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "outputted");
- assert!(output.status.success());
-}
-
-#[test]
-fn dynamic_non_analyzable_import() {
- let _server = http_server();
- let t = TempDir::new();
- t.write(
- "mod.ts",
- "import {Logger} from 'http://localhost:4545/vendor/dynamic_non_analyzable.ts'; new Logger().log('outputted');",
- );
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("vendor")
- .arg("--reload")
- .arg("mod.ts")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- // todo(https://github.com/denoland/deno_graph/issues/138): it should warn about
- // how it couldn't analyze the dynamic import
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- "{}Download http://localhost:4545/vendor/dynamic_non_analyzable.ts\n{}",
- &DEPRECATION_NOTICE,
- success_text("1 module", "vendor/", true),
- )
- );
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
- assert!(output.status.success());
-}
-
-itest!(dynamic_non_existent {
- args: "vendor http://localhost:4545/vendor/dynamic_non_existent.ts",
- temp_cwd: true,
- exit_code: 0,
- http_server: true,
- output: "vendor/dynamic_non_existent.ts.out",
-});
-
-#[test]
-fn update_existing_config_test() {
- let _server = http_server();
- let t = TempDir::new();
- t.write(
- "my_app.ts",
- "import {Logger} from 'http://localhost:4545/vendor/logger.ts'; new Logger().log('outputted');",
- );
- t.write("deno.json", "{\n}");
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .arg("vendor")
- .arg("my_app.ts")
- .arg("--output")
- .arg("vendor2")
- .env("NO_COLOR", "1")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- "{}Download http://localhost:4545/vendor/logger.ts\n{}\n\n{}",
- &DEPRECATION_NOTICE,
- vendored_text("1 module", "vendor2"),
- success_text_updated_deno_json("vendor2",)
- )
- );
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
- assert!(output.status.success());
-
- // try running the output with `--no-remote` and not specifying a `--vendor`
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .env("NO_COLOR", "1")
- .arg("run")
- .arg("--no-remote")
- .arg("--check")
- .arg("--quiet")
- .arg("my_app.ts")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(String::from_utf8_lossy(&output.stderr).trim(), "");
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "outputted");
- assert!(output.status.success());
-}
-
-#[test]
-fn update_existing_empty_config_test() {
- let _server = http_server();
- let t = TempDir::new();
- t.write(
- "my_app.ts",
- "import {Logger} from 'http://localhost:4545/vendor/logger.ts'; new Logger().log('outputted');",
- );
- t.write("deno.json", "");
-
- let deno = util::deno_cmd()
- .current_dir(t.path())
- .arg("vendor")
- .arg("my_app.ts")
- .arg("--output")
- .arg("vendor2")
- .env("NO_COLOR", "1")
- .piped_output()
- .spawn()
- .unwrap();
- let output = deno.wait_with_output().unwrap();
- assert_eq!(
- String::from_utf8_lossy(&output.stderr).trim(),
- format!(
- "⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.
-Add `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead.
-Download http://localhost:4545/vendor/logger.ts\n{}\n\n{}",
- vendored_text("1 module", "vendor2"),
- success_text_updated_deno_json("vendor2",)
- )
- );
- assert_eq!(String::from_utf8_lossy(&output.stdout).trim(), "");
- assert!(output.status.success());
-}
-
-// TODO(2.0): decide if this test should be updated or removed
-#[test]
-#[ignore]
-fn vendor_npm_node_specifiers() {
- let context = TestContextBuilder::for_npm().use_temp_cwd().build();
- let temp_dir = context.temp_dir();
- temp_dir.write(
- "my_app.ts",
- concat!(
- "import { path, getValue, setValue } from 'http://localhost:4545/vendor/npm_and_node_specifier.ts';\n",
- "setValue(5);\n",
- "console.log(path.isAbsolute(Deno.cwd()), getValue());",
- ),
- );
- temp_dir.write("deno.json", "{}");
-
- let output = context.new_command().args("vendor my_app.ts").run();
- output.assert_matches_text(format!(
- concat!(
- "⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.\n",
- "Add `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead.\n",
- "Download http://localhost:4545/vendor/npm_and_node_specifier.ts\n",
- "Download http://localhost:4260/@denotest/esm-basic\n",
- "Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz\n",
- "{}\n",
- "Initialize @denotest/esm-basic@1.0.0\n",
- "{}\n\n",
- "{}\n",
- ),
- vendored_text("1 module", "vendor/"),
- vendored_npm_package_text("1 npm package"),
- success_text_updated_deno_json("vendor/")
- ));
- let output = context.new_command().args("run -A -q my_app.ts").run();
- output.assert_matches_text("true 5\n");
- assert!(temp_dir.path().join("node_modules").exists());
- assert!(temp_dir.path().join("deno.lock").exists());
-
- // now try re-vendoring with a lockfile
- let output = context.new_command().args("vendor --force my_app.ts").run();
- output.assert_matches_text(format!(
- "{}{}\n{}\n\n{}\n",
- &DEPRECATION_NOTICE,
- ignoring_import_map_text(),
- vendored_text("1 module", "vendor/"),
- success_text_updated_deno_json("vendor/"),
- ));
-
- // delete the node_modules folder
- temp_dir.remove_dir_all("node_modules");
-
- // vendor with --node-modules-dir=false
- let output = context
- .new_command()
- .args("vendor --node-modules-dir=false --force my_app.ts")
- .run();
- output.assert_matches_text(format!(
- "{}{}\n{}\n\n{}\n",
- &DEPRECATION_NOTICE,
- ignoring_import_map_text(),
- vendored_text("1 module", "vendor/"),
- success_text_updated_deno_json("vendor/")
- ));
- assert!(!temp_dir.path().join("node_modules").exists());
-
- // delete the deno.json
- temp_dir.remove_file("deno.json");
-
- // vendor with --node-modules-dir
- let output = context
- .new_command()
- .args("vendor --node-modules-dir --force my_app.ts")
- .run();
- output.assert_matches_text(format!(
- "{}Initialize @denotest/esm-basic@1.0.0\n{}\n\n{}\n",
- &DEPRECATION_NOTICE,
- vendored_text("1 module", "vendor/"),
- use_import_map_text("vendor/")
- ));
-}
-
-#[test]
-fn vendor_only_npm_specifiers() {
- let context = TestContextBuilder::for_npm().use_temp_cwd().build();
- let temp_dir = context.temp_dir();
- temp_dir.write(
- "my_app.ts",
- concat!(
- "import { getValue, setValue } from 'npm:@denotest/esm-basic';\n",
- "setValue(5);\n",
- "console.log(path.isAbsolute(Deno.cwd()), getValue());",
- ),
- );
- temp_dir.write("deno.json", "{}");
-
- let output = context.new_command().args("vendor my_app.ts").run();
- output.assert_matches_text(format!(
- concat!(
- "⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.\n",
- "Add `\"vendor\": true` to your `deno.json` or use the `--vendor` flag instead.\n",
- "Download http://localhost:4260/@denotest/esm-basic\n",
- "Download http://localhost:4260/@denotest/esm-basic/1.0.0.tgz\n",
- "{}\n",
- "Initialize @denotest/esm-basic@1.0.0\n",
- "{}\n",
- ),
- vendored_text("0 modules", "vendor/"),
- vendored_npm_package_text("1 npm package"),
- ));
-}
-
-fn success_text(module_count: &str, dir: &str, has_import_map: bool) -> String {
- let mut text = format!("Vendored {module_count} into {dir} directory.");
- if has_import_map {
- write!(text, "\n\n{}", use_import_map_text(dir)).unwrap();
- }
- text
-}
-
-fn use_import_map_text(dir: &str) -> String {
- format!(
- concat!(
- "To use vendored modules, specify the `--import-map {}import_map.json` flag when ",
- r#"invoking Deno subcommands or add an `"importMap": "<path_to_vendored_import_map>"` "#,
- "entry to a deno.json file.",
- ),
- if dir != "vendor/" {
- format!("{}{}", dir.trim_end_matches('/'), if cfg!(windows) { '\\' } else {'/'})
- } else {
- dir.to_string()
- }
- )
-}
-
-fn vendored_text(module_count: &str, dir: &str) -> String {
- format!("Vendored {} into {} directory.", module_count, dir)
-}
-
-fn vendored_npm_package_text(package_count: &str) -> String {
- format!(
- concat!(
- "Vendored {} into node_modules directory. Set `nodeModulesDir: false` ",
- "in the Deno configuration file to disable vendoring npm packages in the future.",
- ),
- package_count
- )
-}
-
-fn success_text_updated_deno_json(dir: &str) -> String {
- format!(
- concat!(
- "Updated your local Deno configuration file with a reference to the ",
- "new vendored import map at {}import_map.json. Invoking Deno subcommands will ",
- "now automatically resolve using the vendored modules. You may override ",
- "this by providing the `--import-map <other-import-map>` flag or by ",
- "manually editing your Deno configuration file.",
- ),
- if dir != "vendor/" {
- format!(
- "{}{}",
- dir.trim_end_matches('/'),
- if cfg!(windows) { '\\' } else { '/' }
- )
- } else {
- dir.to_string()
- }
- )
-}
-
-fn ignoring_import_map_text() -> String {
- format!(
- concat!(
- "Ignoring import map. Specifying an import map file ({}) in the deno ",
- "vendor output directory is not supported. If you wish to use an ",
- "import map while vendoring, please specify one located outside this ",
- "directory.",
- ),
- PathBuf::from("vendor").join("import_map.json").display(),
- )
-}
diff --git a/tests/specs/vendor/removed/__test__.jsonc b/tests/specs/vendor/removed/__test__.jsonc
new file mode 100644
index 000000000..abbcfe465
--- /dev/null
+++ b/tests/specs/vendor/removed/__test__.jsonc
@@ -0,0 +1,13 @@
+{
+ "steps": [
+ {
+ "args": "vendor",
+ "output": "vendor.out",
+ "exitCode": 1
+ },
+ {
+ "args": "vendor --help",
+ "output": "vendor_help.out"
+ }
+ ]
+}
diff --git a/tests/specs/vendor/removed/vendor.out b/tests/specs/vendor/removed/vendor.out
new file mode 100644
index 000000000..ee7e9ca55
--- /dev/null
+++ b/tests/specs/vendor/removed/vendor.out
@@ -0,0 +1,3 @@
+error: ⚠️ `deno vendor` was removed in Deno 2.
+
+See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations
diff --git a/tests/specs/vendor/removed/vendor_help.out b/tests/specs/vendor/removed/vendor_help.out
new file mode 100644
index 000000000..176b2211a
--- /dev/null
+++ b/tests/specs/vendor/removed/vendor_help.out
@@ -0,0 +1,10 @@
+⚠️ `deno vendor` was removed in Deno 2.
+
+See the Deno 1.x to 2.x Migration Guide for migration instructions: https://docs.deno.com/runtime/manual/advanced/migrate_deprecations
+
+Usage: deno vendor [OPTIONS]
+
+Options:
+ -q, --quiet Suppress diagnostic output
+ --unstable Enable all unstable features and APIs. Instead of using this flag, consider enabling individual unstable features
+ To view the list of individual unstable feature flags, run this command again with --help=unstable
diff --git a/tests/testdata/vendor/dynamic.ts b/tests/testdata/vendor/dynamic.ts
deleted file mode 100644
index e2cbb0e59..000000000
--- a/tests/testdata/vendor/dynamic.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-const { Logger } = await import("./logger.ts");
-
-export { Logger };
diff --git a/tests/testdata/vendor/dynamic_non_analyzable.ts b/tests/testdata/vendor/dynamic_non_analyzable.ts
deleted file mode 100644
index 1847939f6..000000000
--- a/tests/testdata/vendor/dynamic_non_analyzable.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-const value = (() => "./logger.ts")();
-const { Logger } = await import(value);
-
-export { Logger };
diff --git a/tests/testdata/vendor/dynamic_non_existent.ts b/tests/testdata/vendor/dynamic_non_existent.ts
deleted file mode 100644
index a48e2accb..000000000
--- a/tests/testdata/vendor/dynamic_non_existent.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-// this should still vendor
-// deno-lint-ignore no-constant-condition
-if (false) {
- await import("./non-existent.js");
-}
-
-export class Logger {
- log(text: string) {
- console.log(text);
- }
-}
diff --git a/tests/testdata/vendor/dynamic_non_existent.ts.out b/tests/testdata/vendor/dynamic_non_existent.ts.out
deleted file mode 100644
index 1bbd01f7b..000000000
--- a/tests/testdata/vendor/dynamic_non_existent.ts.out
+++ /dev/null
@@ -1,9 +0,0 @@
-⚠️ Warning: `deno vendor` is deprecated and will be removed in Deno 2.0.
-Add `"vendor": true` to your `deno.json` or use the `--vendor` flag instead.
-Download http://localhost:4545/vendor/dynamic_non_existent.ts
-Download http://localhost:4545/vendor/non-existent.js
-Ignoring: Dynamic import not found "http://localhost:4545/vendor/non-existent.js".
- at http://localhost:4545/vendor/dynamic_non_existent.ts:4:16
-Vendored 1 module into vendor/ directory.
-
-To use vendored modules, specify the `--import-map vendor/import_map.json` flag when invoking Deno subcommands or add an `"importMap": "<path_to_vendored_import_map>"` entry to a deno.json file.
diff --git a/tests/testdata/vendor/logger.ts b/tests/testdata/vendor/logger.ts
deleted file mode 100644
index 97f603a48..000000000
--- a/tests/testdata/vendor/logger.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export class Logger {
- log(text: string) {
- console.log(text);
- }
-}
diff --git a/tests/testdata/vendor/mod.ts b/tests/testdata/vendor/mod.ts
deleted file mode 100644
index 8824d1b2a..000000000
--- a/tests/testdata/vendor/mod.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./logger.ts";
diff --git a/tests/testdata/vendor/npm_and_node_specifier.ts b/tests/testdata/vendor/npm_and_node_specifier.ts
deleted file mode 100644
index 61962e836..000000000
--- a/tests/testdata/vendor/npm_and_node_specifier.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export { default as path } from "node:path";
-export { getValue, setValue } from "npm:@denotest/esm-basic";
diff --git a/tests/testdata/vendor/query_reexport.ts b/tests/testdata/vendor/query_reexport.ts
deleted file mode 100644
index 5dfafb532..000000000
--- a/tests/testdata/vendor/query_reexport.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from "./logger.ts?test";