swc_node_bundler/v1/
mod.rs1use std::{collections::HashMap, fmt, marker::PhantomData, path::PathBuf};
2
3use rustc_hash::FxHashMap;
4use serde::Deserialize;
5use string_enum::StringEnum;
6use swc_atoms::Atom;
7use swc_common::FileName;
8use swc_ecma_ast::EsVersion;
9use swc_ecma_loader::TargetEnv;
10
11pub use self::{
12 module::ModuleConfig,
13 optimization::OptimizationConfig,
14 output::OutputConfig,
15 resolve::{AliasConfig, ResolveConfig},
16};
17
18mod module;
19mod optimization;
20mod output;
21mod resolve;
22
23#[derive(Debug, Deserialize)]
24#[serde(rename_all = "camelCase")]
25pub struct Config {
26 #[serde(default)]
27 pub working_dir: PathBuf,
28
29 #[serde(default)]
30 pub mode: Mode,
31
32 #[serde(default)]
33 pub target: TargetEnv,
34
35 pub entry: EntryConfig,
36
37 #[serde(default)]
38 pub output: Option<OutputConfig>,
39
40 #[serde(default)]
41 pub module: ModuleConfig,
42
43 #[serde(default)]
44 pub optimization: Option<OptimizationConfig>,
45
46 #[serde(default)]
47 pub resolve: Option<ResolveConfig>,
48
49 #[serde(default)]
50 pub options: Option<swc::config::Options>,
51
52 #[serde(default)]
53 pub external_modules: Vec<Atom>,
54
55 #[serde(default)]
56 pub alias: FxHashMap<TargetEnv, FxHashMap<String, String>>,
57
58 #[serde(default)]
59 pub preserve_symlinks: bool,
60}
61
62impl Config {
63 pub fn codegen_target(&self) -> Option<EsVersion> {
64 self.options
65 .as_ref()
66 .and_then(|options| options.codegen_target())
67 }
68}
69
70#[derive(StringEnum, Default)]
71pub enum Mode {
72 Production,
74 Debug,
76 #[default]
78 None,
79}
80
81#[derive(Debug, Clone, Deserialize)]
82#[serde(untagged, rename = "Entry")]
83pub enum EntryConfig {
84 File(String),
85 Multiple(Vec<String>),
86 Files(FxHashMap<String, PathBuf>),
87}
88
89impl From<EntryConfig> for HashMap<String, FileName> {
90 fn from(c: EntryConfig) -> Self {
91 let mut m = HashMap::default();
92
93 match c {
94 EntryConfig::File(f) => {
95 let path = PathBuf::from(f);
96 let file_name = path
97 .file_name()
98 .expect("entry must be a file, instead of a directory");
99 m.insert(file_name.to_string_lossy().into(), FileName::Real(path));
100 }
101 EntryConfig::Multiple(files) => {
102 for f in files {
103 let path = PathBuf::from(f);
104 let file_name = path
105 .file_name()
106 .expect("entry must be a file, instead of a directory");
107 m.insert(file_name.to_string_lossy().into(), FileName::Real(path));
108 }
109 }
110 EntryConfig::Files(f) => {
111 return f.into_iter().map(|(k, v)| (k, FileName::Real(v))).collect()
112 }
113 }
114
115 m
116 }
117}
118
119pub struct JsCallback<T, Ret> {
120 _f: Box<dyn Send + Sync + Fn(T) -> Ret>,
121 _phantom: PhantomData<(T, Ret)>,
122}
123
124impl<T, Ret> fmt::Debug for JsCallback<T, Ret> {
125 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
126 write!(f, "<js function>")
127 }
128}