waterui_cli/
backend.rs

1//! Backend configuration and initialization for `WaterUI` projects.
2
3use std::path::Path;
4
5use serde::{Deserialize, Serialize};
6
7use crate::{android::backend::AndroidBackend, apple::backend::AppleBackend, project::Project};
8
9/// Configuration for all backends in a `WaterUI` project.
10///
11/// `[backend]` in `Water.toml`
12#[derive(Debug, Serialize, Deserialize, Clone, Default)]
13pub struct Backends {
14    /// Base path for all backends, relative to project root.
15    /// Empty string means project root (for apps), `.water` for playgrounds.
16    #[serde(default, skip_serializing_if = "String::is_empty")]
17    path: String,
18    android: Option<AndroidBackend>,
19    apple: Option<AppleBackend>,
20}
21
22impl Backends {
23    /// Check if no backends are configured.
24    #[must_use]
25    pub const fn is_empty(&self) -> bool {
26        self.android.is_none() && self.apple.is_none()
27    }
28
29    /// Get the base path for backends, relative to project root.
30    #[must_use]
31    pub fn path(&self) -> &Path {
32        Path::new(&self.path)
33    }
34
35    /// Set the base path for backends.
36    pub fn set_path(&mut self, path: impl Into<String>) {
37        self.path = path.into();
38    }
39
40    /// Get the Android backend configuration, if any.
41    #[must_use]
42    pub const fn android(&self) -> Option<&AndroidBackend> {
43        self.android.as_ref()
44    }
45
46    /// Get the Apple backend configuration, if any.
47    #[must_use]
48    pub const fn apple(&self) -> Option<&AppleBackend> {
49        self.apple.as_ref()
50    }
51
52    /// Set the Apple backend configuration.
53    pub fn set_apple(&mut self, backend: AppleBackend) {
54        self.apple = Some(backend);
55    }
56
57    /// Set the Android backend configuration.
58    pub fn set_android(&mut self, backend: AndroidBackend) {
59        self.android = Some(backend);
60    }
61}
62
63/// Error type for failing to initialize a backend.
64#[derive(Debug, thiserror::Error)]
65pub enum FailToInitBackend {
66    /// I/O error while scaffolding templates.
67    #[error("Failed to write template files: {0}")]
68    Io(#[from] std::io::Error),
69}
70
71/// Trait for backends in a `WaterUI` project.
72pub trait Backend: Sized + Send + Sync {
73    /// The default relative path for this backend (e.g., "android", "apple").
74    const DEFAULT_PATH: &'static str;
75
76    /// Get the relative path for this backend instance.
77    ///
78    /// This is relative to `Backends::path()`.
79    fn path(&self) -> &Path;
80
81    /// Initialize the backend for the given project.
82    ///
83    /// Creates necessary files/folders for the backend at `project.backend_path::<Self>()`.
84    /// Returns the initialized backend configuration.
85    fn init(project: &Project) -> impl Future<Output = Result<Self, FailToInitBackend>> + Send;
86}