summaryrefslogtreecommitdiff
path: root/cli/tools/bundle.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/bundle.rs')
-rw-r--r--cli/tools/bundle.rs158
1 files changed, 158 insertions, 0 deletions
diff --git a/cli/tools/bundle.rs b/cli/tools/bundle.rs
new file mode 100644
index 000000000..606bab46f
--- /dev/null
+++ b/cli/tools/bundle.rs
@@ -0,0 +1,158 @@
+// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
+
+use std::path::PathBuf;
+use std::sync::Arc;
+
+use deno_core::error::AnyError;
+use deno_core::futures::FutureExt;
+use deno_core::resolve_url_or_path;
+use deno_runtime::colors;
+
+use crate::args::BundleFlags;
+use crate::args::CliOptions;
+use crate::args::Flags;
+use crate::args::TsConfigType;
+use crate::args::TypeCheckMode;
+use crate::graph_util::create_graph_and_maybe_check;
+use crate::graph_util::error_for_any_npm_specifier;
+use crate::proc_state::ProcState;
+use crate::util;
+use crate::util::display;
+use crate::util::file_watcher::ResolutionResult;
+
+pub async fn bundle(
+ flags: Flags,
+ bundle_flags: BundleFlags,
+) -> Result<(), AnyError> {
+ let cli_options = Arc::new(CliOptions::from_flags(flags)?);
+ let resolver = |_| {
+ let cli_options = cli_options.clone();
+ let source_file1 = bundle_flags.source_file.clone();
+ let source_file2 = bundle_flags.source_file.clone();
+ async move {
+ let module_specifier = resolve_url_or_path(&source_file1)?;
+
+ log::debug!(">>>>> bundle START");
+ let ps = ProcState::from_options(cli_options).await?;
+ let graph = create_graph_and_maybe_check(module_specifier, &ps).await?;
+
+ let mut paths_to_watch: Vec<PathBuf> = graph
+ .specifiers()
+ .filter_map(|(_, r)| {
+ r.as_ref().ok().and_then(|(s, _, _)| s.to_file_path().ok())
+ })
+ .collect();
+
+ if let Ok(Some(import_map_path)) = ps
+ .options
+ .resolve_import_map_specifier()
+ .map(|ms| ms.and_then(|ref s| s.to_file_path().ok()))
+ {
+ paths_to_watch.push(import_map_path);
+ }
+
+ Ok((paths_to_watch, graph, ps))
+ }
+ .map(move |result| match result {
+ Ok((paths_to_watch, graph, ps)) => ResolutionResult::Restart {
+ paths_to_watch,
+ result: Ok((ps, graph)),
+ },
+ Err(e) => ResolutionResult::Restart {
+ paths_to_watch: vec![PathBuf::from(source_file2)],
+ result: Err(e),
+ },
+ })
+ };
+
+ let operation = |(ps, graph): (ProcState, Arc<deno_graph::ModuleGraph>)| {
+ let out_file = bundle_flags.out_file.clone();
+ async move {
+ // at the moment, we don't support npm specifiers in deno bundle, so show an error
+ error_for_any_npm_specifier(&graph)?;
+
+ let bundle_output = bundle_module_graph(graph.as_ref(), &ps)?;
+ log::debug!(">>>>> bundle END");
+
+ if let Some(out_file) = out_file.as_ref() {
+ let output_bytes = bundle_output.code.as_bytes();
+ let output_len = output_bytes.len();
+ util::fs::write_file(out_file, output_bytes, 0o644)?;
+ log::info!(
+ "{} {:?} ({})",
+ colors::green("Emit"),
+ out_file,
+ colors::gray(display::human_size(output_len as f64))
+ );
+ if let Some(bundle_map) = bundle_output.maybe_map {
+ let map_bytes = bundle_map.as_bytes();
+ let map_len = map_bytes.len();
+ let ext = if let Some(curr_ext) = out_file.extension() {
+ format!("{}.map", curr_ext.to_string_lossy())
+ } else {
+ "map".to_string()
+ };
+ let map_out_file = out_file.with_extension(ext);
+ util::fs::write_file(&map_out_file, map_bytes, 0o644)?;
+ log::info!(
+ "{} {:?} ({})",
+ colors::green("Emit"),
+ map_out_file,
+ colors::gray(display::human_size(map_len as f64))
+ );
+ }
+ } else {
+ println!("{}", bundle_output.code);
+ }
+
+ Ok(())
+ }
+ };
+
+ if cli_options.watch_paths().is_some() {
+ util::file_watcher::watch_func(
+ resolver,
+ operation,
+ util::file_watcher::PrintConfig {
+ job_name: "Bundle".to_string(),
+ clear_screen: !cli_options.no_clear_screen(),
+ },
+ )
+ .await?;
+ } else {
+ let module_graph =
+ if let ResolutionResult::Restart { result, .. } = resolver(None).await {
+ result?
+ } else {
+ unreachable!();
+ };
+ operation(module_graph).await?;
+ }
+
+ Ok(())
+}
+
+fn bundle_module_graph(
+ graph: &deno_graph::ModuleGraph,
+ ps: &ProcState,
+) -> Result<deno_emit::BundleEmit, AnyError> {
+ log::info!("{} {}", colors::green("Bundle"), graph.roots[0].0);
+
+ let ts_config_result = ps
+ .options
+ .resolve_ts_config_for_emit(TsConfigType::Bundle)?;
+ if ps.options.type_check_mode() == TypeCheckMode::None {
+ if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
+ eprintln!("{}", ignored_options);
+ }
+ }
+
+ deno_emit::bundle_graph(
+ graph,
+ deno_emit::BundleOptions {
+ bundle_type: deno_emit::BundleType::Module,
+ emit_options: ts_config_result.ts_config.into(),
+ emit_ignore_directives: true,
+ },
+ )
+}