supabase_client_core/
client.rs1use std::sync::Arc;
2
3#[cfg(feature = "direct-sql")]
4use sqlx::postgres::PgPoolOptions;
5#[cfg(feature = "direct-sql")]
6use sqlx::PgPool;
7
8use crate::config::SupabaseConfig;
9use crate::error::SupabaseResult;
10
11#[derive(Debug, Clone)]
16pub struct SupabaseClient {
17 config: Arc<SupabaseConfig>,
18 http: reqwest::Client,
19 #[cfg(feature = "direct-sql")]
20 pool: Option<Arc<PgPool>>,
21}
22
23impl SupabaseClient {
24 pub fn new(config: SupabaseConfig) -> SupabaseResult<Self> {
28 let http = reqwest::Client::new();
29 Ok(Self {
30 config: Arc::new(config),
31 http,
32 #[cfg(feature = "direct-sql")]
33 pool: None,
34 })
35 }
36
37 #[cfg(feature = "direct-sql")]
41 pub async fn with_database(config: SupabaseConfig) -> SupabaseResult<Self> {
42 let db_url = config
43 .database_url
44 .as_ref()
45 .ok_or_else(|| crate::error::SupabaseError::Config(
46 "database_url is required for direct-sql mode".into(),
47 ))?;
48
49 let pool = PgPoolOptions::new()
50 .max_connections(config.pool.max_connections)
51 .min_connections(config.pool.min_connections)
52 .acquire_timeout(config.pool.acquire_timeout)
53 .idle_timeout(config.pool.idle_timeout)
54 .max_lifetime(config.pool.max_lifetime)
55 .connect(db_url)
56 .await?;
57
58 let http = reqwest::Client::new();
59
60 Ok(Self {
61 config: Arc::new(config),
62 http,
63 pool: Some(Arc::new(pool)),
64 })
65 }
66
67 #[cfg(feature = "direct-sql")]
69 pub fn from_pool(pool: PgPool, config: SupabaseConfig) -> Self {
70 Self {
71 config: Arc::new(config),
72 http: reqwest::Client::new(),
73 pool: Some(Arc::new(pool)),
74 }
75 }
76
77 pub fn http(&self) -> &reqwest::Client {
79 &self.http
80 }
81
82 pub fn supabase_url(&self) -> &str {
84 &self.config.supabase_url
85 }
86
87 pub fn api_key(&self) -> &str {
89 &self.config.supabase_key
90 }
91
92 pub fn schema(&self) -> &str {
94 &self.config.schema
95 }
96
97 pub fn config(&self) -> &SupabaseConfig {
99 &self.config
100 }
101
102 #[cfg(feature = "direct-sql")]
104 pub fn pool(&self) -> Option<&PgPool> {
105 self.pool.as_deref()
106 }
107
108 #[cfg(feature = "direct-sql")]
110 pub fn pool_arc(&self) -> Option<Arc<PgPool>> {
111 self.pool.clone()
112 }
113
114 #[cfg(feature = "direct-sql")]
116 pub fn has_pool(&self) -> bool {
117 self.pool.is_some()
118 }
119
120 #[cfg(feature = "direct-sql")]
122 pub async fn close(&self) {
123 if let Some(pool) = &self.pool {
124 pool.close().await;
125 }
126 }
127
128 #[cfg(feature = "direct-sql")]
130 pub fn is_closed(&self) -> bool {
131 self.pool.as_ref().map_or(true, |p| p.is_closed())
132 }
133}