Skip to main content

storage_kit/databases/config/
mod.rs

1//! Built-in database configuration.
2
3mod common;
4mod lance;
5mod surreal;
6
7use serde::{Deserialize, Serialize};
8
9use crate::StorageError;
10
11pub use common::CommonConfig;
12pub use lance::LanceConfig;
13pub use surreal::{SurrealConfig, SurrealModeConfig};
14
15/// Selects and configures one built-in database implementation.
16///
17/// Shared portable connection policy is carried directly by each variant, so
18/// construction has one configuration owner rather than a wrapper around a
19/// second backend-selection enum.
20///
21/// LanceDB is always available. SurrealDB requires `surrealdb`.
22/// Configuration values do not open backend resources.
23/// These constructors create data only; [`crate::Database::connect`] opens it.
24///
25/// # Examples
26///
27/// ```
28/// use storage_kit::database::config::{DatabaseConfig, LanceConfig};
29/// let config = DatabaseConfig::lance(LanceConfig::embedded_path("memory://"));
30/// config.validate()?;
31/// assert_eq!(config.common().request_timeout_ms, 30_000);
32/// # Ok::<(), storage_kit::StorageError>(())
33/// ```
34#[derive(Clone, Debug, Serialize, Deserialize)]
35pub enum DatabaseConfig {
36    /// Opens LanceDB.
37    Lance {
38        /// LanceDB-specific settings.
39        config: LanceConfig,
40        /// Shared portable connection policy.
41        common: CommonConfig,
42    },
43    /// Opens SurrealDB.
44    Surreal {
45        /// SurrealDB-specific settings.
46        config: SurrealConfig,
47        /// Shared portable connection policy.
48        common: CommonConfig,
49    },
50}
51
52impl DatabaseConfig {
53    /// Selects LanceDB with default shared connection policy.
54    ///
55    /// # Examples
56    ///
57    /// ```
58    /// use storage_kit::database::config::{DatabaseConfig, LanceConfig};
59    /// let config = DatabaseConfig::lance(LanceConfig::embedded_path("memory://"));
60    /// config.validate()?;
61    /// # Ok::<(), storage_kit::StorageError>(())
62    /// ```
63    #[must_use]
64    pub fn lance(config: LanceConfig) -> Self {
65        Self::Lance {
66            config,
67            common: CommonConfig::default(),
68        }
69    }
70
71    /// Selects SurrealDB with default shared connection policy.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use storage_kit::database::config::{DatabaseConfig, SurrealConfig};
77    /// let config = DatabaseConfig::surreal(SurrealConfig::default());
78    /// config.validate()?;
79    /// # Ok::<(), storage_kit::StorageError>(())
80    /// ```
81    #[must_use]
82    pub fn surreal(config: SurrealConfig) -> Self {
83        Self::Surreal {
84            config,
85            common: CommonConfig::default(),
86        }
87    }
88
89    /// Replaces the shared connection policy carried by this variant.
90    ///
91    /// # Examples
92    ///
93    /// ```
94    /// use storage_kit::database::config::{CommonConfig, DatabaseConfig, LanceConfig};
95    /// let config = DatabaseConfig::lance(LanceConfig::embedded_path("memory://"))
96    ///     .with_common(CommonConfig { read_only: true, ..Default::default() });
97    /// assert!(config.common().read_only);
98    /// # Ok::<(), storage_kit::StorageError>(())
99    /// ```
100    #[must_use]
101    pub fn with_common(self, common: CommonConfig) -> Self {
102        match self {
103            Self::Lance { config, .. } => Self::Lance { config, common },
104            Self::Surreal { config, .. } => Self::Surreal { config, common },
105        }
106    }
107
108    /// Borrows the shared connection policy.
109    ///
110    /// # Examples
111    ///
112    /// ```
113    /// use storage_kit::database::config::{DatabaseConfig, LanceConfig};
114    /// let config = DatabaseConfig::lance(LanceConfig::embedded_path("memory://"));
115    /// assert_eq!(config.common().connect_timeout_ms, 15_000);
116    /// # Ok::<(), storage_kit::StorageError>(())
117    /// ```
118    #[must_use]
119    pub fn common(&self) -> &CommonConfig {
120        match self {
121            Self::Lance { common, .. } | Self::Surreal { common, .. } => common,
122        }
123    }
124
125    /// Validates shared policy and backend-specific settings.
126    ///
127    /// This checks configuration without opening a connection or proving service
128    /// availability or request-specific capability support.
129    ///
130    /// # Errors
131    ///
132    /// Returns [`StorageError::InvalidConfig`] for zero timeouts, invalid default
133    /// locator fragments, or invalid selected backend settings, such as an empty
134    /// embedded path, unsupported URI route, or wrong remote URL scheme.
135    ///
136    /// # Examples
137    ///
138    /// ```
139    /// use storage_kit::database::config::{DatabaseConfig, LanceConfig};
140    /// let valid = DatabaseConfig::lance(LanceConfig::embedded_path("memory://"));
141    /// valid.validate()?;
142    /// let invalid = DatabaseConfig::lance(LanceConfig::embedded_path("s3://bucket/data"));
143    /// assert!(invalid.validate().is_err());
144    /// # Ok::<(), storage_kit::StorageError>(())
145    /// ```
146    pub fn validate(&self) -> Result<(), StorageError> {
147        self.common().validate()?;
148        match self {
149            Self::Lance { config, .. } => config.validate(),
150            Self::Surreal { config, .. } => config.validate(),
151        }
152    }
153}
154
155impl From<LanceConfig> for DatabaseConfig {
156    fn from(config: LanceConfig) -> Self {
157        Self::lance(config)
158    }
159}
160
161impl From<SurrealConfig> for DatabaseConfig {
162    fn from(config: SurrealConfig) -> Self {
163        Self::surreal(config)
164    }
165}