solidb_client/client/
builder.rs1use super::DriverError;
2use super::SoliDBClient;
3use super::HttpClient;
4
5pub struct SoliDBClientBuilder {
6 addr: String,
7 auth: Option<AuthMethod>,
8 timeout_ms: Option<u64>,
9 pool_size: Option<usize>,
10 transport: Transport,
11}
12
13pub enum AuthMethod {
14 UsernamePassword {
15 database: String,
16 username: String,
17 password: String,
18 },
19 ApiKey {
20 database: String,
21 api_key: String,
22 },
23}
24
25#[derive(Clone, Copy, Default)]
26pub enum Transport {
27 #[default]
28 Http,
29 Tcp,
30}
31
32impl SoliDBClientBuilder {
33 pub fn new(addr: &str) -> Self {
34 let addr = addr.to_string();
35 let is_http = addr.starts_with("http://") || addr.starts_with("https://");
36
37 Self {
38 addr,
39 auth: None,
40 timeout_ms: None,
41 pool_size: None,
42 transport: if is_http { Transport::Http } else { Transport::Tcp },
43 }
44 }
45
46 pub fn auth(mut self, database: &str, username: &str, password: &str) -> Self {
47 self.auth = Some(AuthMethod::UsernamePassword {
48 database: database.to_string(),
49 username: username.to_string(),
50 password: password.to_string(),
51 });
52 self
53 }
54
55 pub fn auth_with_api_key(mut self, database: &str, api_key: &str) -> Self {
56 self.auth = Some(AuthMethod::ApiKey {
57 database: database.to_string(),
58 api_key: api_key.to_string(),
59 });
60 self
61 }
62
63 pub fn timeout_ms(mut self, ms: u64) -> Self {
64 self.timeout_ms = Some(ms);
65 self
66 }
67
68 pub fn pool_size(mut self, size: usize) -> Self {
69 self.pool_size = Some(size);
70 self
71 }
72
73 pub fn use_http(mut self) -> Self {
74 self.transport = Transport::Http;
75 self
76 }
77
78 pub fn use_tcp(mut self) -> Self {
79 self.transport = Transport::Tcp;
80 self
81 }
82
83 pub async fn build_http(self) -> Result<HttpClient, DriverError> {
84 let mut client = HttpClient::new(&self.addr);
85
86 if let Some(database) = self.auth.as_ref().map(|a| match a {
87 AuthMethod::UsernamePassword { database, .. } => database.clone(),
88 AuthMethod::ApiKey { database, .. } => database.clone(),
89 }) {
90 client.set_database(&database);
91 }
92
93 if let Some(auth) = self.auth {
94 match auth {
95 AuthMethod::UsernamePassword {
96 database,
97 username,
98 password,
99 } => {
100 client.login(&database, &username, &password).await?;
101 }
102 AuthMethod::ApiKey { database, api_key } => {
103 let mut http_client = HttpClient::new(&self.addr);
104 http_client.set_database(&database);
105 http_client.set_token(&api_key);
106 return Ok(http_client);
107 }
108 }
109 }
110
111 Ok(client)
112 }
113
114 pub async fn build(self) -> Result<SoliDBClient, DriverError> {
115 match self.transport {
116 Transport::Http => {
117 let _ = self.build_http().await?;
118 Err(DriverError::ProtocolError(
119 "Use build_http() for HTTP transport. For TCP, use .use_tcp() or a host:port address.".to_string(),
120 ))
121 }
122 Transport::Tcp => {
123 let pool_size = self.pool_size.unwrap_or(4);
124 let mut client = SoliDBClient::connect_with_pool(&self.addr, pool_size).await?;
125
126 if let Some(auth) = self.auth {
127 match auth {
128 AuthMethod::UsernamePassword {
129 database,
130 username,
131 password,
132 } => {
133 client.auth(&database, &username, &password).await?;
134 }
135 AuthMethod::ApiKey { database, api_key } => {
136 client.auth_with_api_key(&database, &api_key).await?;
137 }
138 }
139 }
140
141 Ok(client)
142 }
143 }
144 }
145
146 pub async fn build_with_transport(self) -> Result<SoliDBClient, DriverError> {
147 match self.transport {
148 Transport::Http => {
149 let _ = self.build_http().await?;
150 Err(DriverError::ProtocolError(
151 "HTTP transport selected but build() was called. Use build_http() instead.".to_string(),
152 ))
153 }
154 Transport::Tcp => self.build().await,
155 }
156 }
157}