swc_node_bundler/v1/
mod.rs

1use 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`
73    Production,
74    /// `debug`
75    Debug,
76    /// `none`
77    #[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}