fob_cli/config/
mod.rs

1//! Configuration system for Fob bundler with multi-source loading.
2//!
3//! Merges settings from CLI args, environment variables, and config files.
4//! Priority: CLI > Environment > File > Defaults
5
6mod conversions;
7mod defaults;
8mod loading;
9mod tests;
10mod types;
11mod validation;
12
13use schemars::JsonSchema;
14use serde::{Deserialize, Serialize};
15use std::path::PathBuf;
16
17pub use defaults::*;
18pub use types::*;
19pub use validation::*;
20
21/// Fob configuration - loaded from fob.config.json or CLI args.
22#[derive(Debug, Clone, Serialize, Deserialize, JsonSchema)]
23#[serde(rename_all = "camelCase", deny_unknown_fields)]
24pub struct FobConfig {
25    /// Entry points to bundle (e.g., ["src/index.ts"])
26    pub entry: Vec<String>,
27
28    /// Output format (esm, cjs, iife)
29    #[serde(default = "default_format")]
30    pub format: Format,
31
32    /// Output directory
33    #[serde(default = "default_out_dir")]
34    pub out_dir: PathBuf,
35
36    /// Generate TypeScript declarations
37    #[serde(default)]
38    pub dts: bool,
39
40    /// Bundle declarations into single .d.ts file (requires dts: true)
41    #[serde(default, skip_serializing_if = "Option::is_none")]
42    pub dts_bundle: Option<bool>,
43
44    /// External packages to exclude from bundle
45    #[serde(default, skip_serializing_if = "Vec::is_empty")]
46    pub external: Vec<String>,
47
48    /// Target platform
49    #[serde(default = "default_platform")]
50    pub platform: Platform,
51
52    /// Source map mode
53    #[serde(skip_serializing_if = "Option::is_none")]
54    pub sourcemap: Option<SourceMapMode>,
55
56    /// Enable minification
57    #[serde(default)]
58    pub minify: bool,
59
60    /// JavaScript target version
61    #[serde(default = "default_target")]
62    pub target: EsTarget,
63
64    /// Global variable name for IIFE bundles (must be valid JS identifier)
65    #[schemars(regex(pattern = r"^[a-zA-Z_$][a-zA-Z0-9_$]*$"))]
66    #[serde(skip_serializing_if = "Option::is_none")]
67    pub global_name: Option<String>,
68
69    /// Bundle dependencies into output
70    /// - true: Include all dependencies in the bundle
71    /// - false: Externalize dependencies (library mode)
72    #[serde(default = "default_bundle")]
73    pub bundle: bool,
74
75    /// Enable code splitting
76    #[serde(default)]
77    pub splitting: bool,
78
79    /// Disable tree shaking
80    #[serde(default)]
81    pub no_treeshake: bool,
82
83    /// Clean output directory before build
84    #[serde(default)]
85    pub clean: bool,
86
87    /// Working directory
88    #[serde(skip_serializing_if = "Option::is_none")]
89    pub cwd: Option<PathBuf>,
90}
91
92impl FobConfig {
93    /// Generate JSON Schema for fob.config.json.
94    pub fn json_schema() -> serde_json::Value {
95        let schema = schemars::schema_for!(FobConfig);
96        serde_json::to_value(schema).expect("Schema serialization should never fail")
97    }
98
99    /// Generate example fob.config.json content.
100    pub fn example_config() -> String {
101        use std::path::PathBuf;
102        use types::*;
103
104        serde_json::to_string_pretty(&Self {
105            entry: vec!["src/index.ts".to_string(), "src/cli.ts".to_string()],
106            format: Format::Esm,
107            out_dir: PathBuf::from("dist"),
108            dts: true,
109            dts_bundle: Some(true),
110            external: vec!["react".to_string(), "react-dom".to_string()],
111            platform: Platform::Browser,
112            sourcemap: Some(SourceMapMode::External),
113            minify: true,
114            target: EsTarget::Es2020,
115            global_name: None,
116            bundle: true,
117            splitting: true,
118            no_treeshake: false,
119            clean: true,
120            cwd: None,
121        })
122        .expect("Example config serialization should never fail")
123    }
124}