Skip to main content

ferro_inertia/
config.rs

1//! Configuration for Inertia.js integration.
2
3/// Configuration for Inertia.js responses.
4///
5/// # Example
6///
7/// ```rust
8/// use ferro_inertia::InertiaConfig;
9///
10/// // Development configuration (default)
11/// let config = InertiaConfig::default();
12///
13/// // Production configuration
14/// let config = InertiaConfig::new()
15///     .version("1.0.0")
16///     .production();
17///
18/// // Custom Vite dev server
19/// let config = InertiaConfig::new()
20///     .vite_dev_server("http://localhost:3000")
21///     .entry_point("src/app.tsx");
22/// ```
23#[derive(Debug, Clone)]
24pub struct InertiaConfig {
25    /// Application name used in the HTML title tag
26    pub app_name: String,
27    /// Vite dev server URL (e.g., "http://localhost:5173")
28    pub vite_dev_server: String,
29    /// Entry point for the frontend (e.g., "src/main.tsx")
30    pub entry_point: String,
31    /// Asset version for cache busting
32    pub version: String,
33    /// Whether we're in development mode (use Vite dev server)
34    pub development: bool,
35    /// Custom HTML template (if None, uses default)
36    pub html_template: Option<String>,
37    /// Path to Vite's manifest.json for resolving hashed asset filenames
38    pub manifest_path: String,
39}
40
41impl Default for InertiaConfig {
42    fn default() -> Self {
43        let vite_dev_server = std::env::var("VITE_DEV_SERVER")
44            .unwrap_or_else(|_| "http://localhost:5173".to_string());
45
46        let is_dev = !matches!(
47            std::env::var("APP_ENV").ok().as_deref(),
48            Some("production") | Some("staging")
49        );
50
51        let app_name = std::env::var("APP_NAME").unwrap_or_else(|_| "Ferro".to_string());
52
53        Self {
54            app_name,
55            vite_dev_server,
56            entry_point: "src/main.tsx".to_string(),
57            version: "1.0".to_string(),
58            development: is_dev,
59            html_template: None,
60            manifest_path: "public/.vite/manifest.json".to_string(),
61        }
62    }
63}
64
65impl InertiaConfig {
66    /// Create a new configuration with default values.
67    pub fn new() -> Self {
68        Self::default()
69    }
70
71    /// Set the Vite dev server URL.
72    pub fn vite_dev_server(mut self, url: impl Into<String>) -> Self {
73        self.vite_dev_server = url.into();
74        self
75    }
76
77    /// Set the frontend entry point.
78    pub fn entry_point(mut self, entry: impl Into<String>) -> Self {
79        self.entry_point = entry.into();
80        self
81    }
82
83    /// Set the asset version for cache busting.
84    pub fn version(mut self, version: impl Into<String>) -> Self {
85        self.version = version.into();
86        self
87    }
88
89    /// Enable production mode (disables Vite dev server integration).
90    pub fn production(mut self) -> Self {
91        self.development = false;
92        self
93    }
94
95    /// Enable development mode (enables Vite dev server integration).
96    pub fn development(mut self) -> Self {
97        self.development = true;
98        self
99    }
100
101    /// Set the application name used in the HTML title tag.
102    pub fn app_name(mut self, name: impl Into<String>) -> Self {
103        self.app_name = name.into();
104        self
105    }
106
107    /// Set the path to Vite's manifest.json.
108    pub fn manifest_path(mut self, path: impl Into<String>) -> Self {
109        self.manifest_path = path.into();
110        self
111    }
112
113    /// Set a custom HTML template.
114    ///
115    /// The template should contain the following placeholders:
116    /// - `{page}` - The escaped JSON page data
117    /// - `{csrf}` - The CSRF token (optional)
118    ///
119    /// # Example
120    ///
121    /// ```rust
122    /// use ferro_inertia::InertiaConfig;
123    ///
124    /// let template = r#"
125    /// <!DOCTYPE html>
126    /// <html>
127    /// <head><title>My App</title></head>
128    /// <body>
129    ///     <div id="app" data-page="{page}"></div>
130    ///     <script src="/app.js"></script>
131    /// </body>
132    /// </html>
133    /// "#;
134    ///
135    /// let config = InertiaConfig::new()
136    ///     .html_template(template);
137    /// ```
138    pub fn html_template(mut self, template: impl Into<String>) -> Self {
139        self.html_template = Some(template.into());
140        self
141    }
142}