Skip to main content

supabase_rust/
client.rs

1use std::env;
2
3use reqwest::Client;
4
5use crate::Supabase;
6
7impl Supabase {
8    /// Creates a new Supabase client.
9    ///
10    /// `url` and `api_key` are required — they must be provided as arguments or
11    /// set via the `SUPABASE_URL` and `SUPABASE_API_KEY` environment variables.
12    /// Returns `Error::Config` if either value is missing or empty.
13    ///
14    /// `jwt` is optional and defaults to an empty string when not provided.
15    pub fn new(
16        url: Option<&str>,
17        api_key: Option<&str>,
18        jwt: Option<&str>,
19    ) -> Result<Self, crate::Error> {
20        let url = url
21            .map(Into::into)
22            .or_else(|| env::var("SUPABASE_URL").ok())
23            .filter(|s: &String| !s.is_empty())
24            .ok_or_else(|| {
25                crate::Error::Config(
26                    "missing SUPABASE_URL: provide as argument or set the environment variable"
27                        .into(),
28                )
29            })?;
30
31        let api_key = api_key
32            .map(Into::into)
33            .or_else(|| env::var("SUPABASE_API_KEY").ok())
34            .filter(|s: &String| !s.is_empty())
35            .ok_or_else(|| {
36                crate::Error::Config(
37                    "missing SUPABASE_API_KEY: provide as argument or set the environment variable"
38                        .into(),
39                )
40            })?;
41
42        let jwt = jwt
43            .map(Into::into)
44            .unwrap_or_else(|| env::var("SUPABASE_JWT_SECRET").unwrap_or_default());
45
46        Ok(Self {
47            client: Client::new(),
48            url,
49            api_key,
50            jwt,
51            bearer_token: None,
52        })
53    }
54
55    /// Sets the bearer token for authenticated requests.
56    pub fn set_bearer_token(&mut self, token: impl Into<String>) {
57        self.bearer_token = Some(token.into());
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::*;
64
65    #[test]
66    fn test_client_creation() {
67        let client = Supabase::new(
68            Some("https://example.supabase.co"),
69            Some("test-key"),
70            Some("test-jwt"),
71        )
72        .unwrap();
73        assert_eq!(client.url, "https://example.supabase.co");
74        assert_eq!(client.api_key, "test-key");
75        assert_eq!(client.jwt, "test-jwt");
76    }
77
78    #[test]
79    fn test_client_missing_url() {
80        // Temporarily remove the env var so the constructor can't fall back to it
81        let saved = env::var("SUPABASE_URL").ok();
82        env::remove_var("SUPABASE_URL");
83
84        let result = Supabase::new(None, Some("key"), None);
85        assert!(result.is_err());
86        let err = result.unwrap_err();
87        assert!(matches!(err, crate::Error::Config(_)));
88
89        if let Some(val) = saved {
90            env::set_var("SUPABASE_URL", val);
91        }
92    }
93
94    #[test]
95    fn test_client_missing_api_key() {
96        let saved = env::var("SUPABASE_API_KEY").ok();
97        env::remove_var("SUPABASE_API_KEY");
98
99        let result = Supabase::new(Some("https://example.supabase.co"), None, None);
100        assert!(result.is_err());
101        let err = result.unwrap_err();
102        assert!(matches!(err, crate::Error::Config(_)));
103
104        if let Some(val) = saved {
105            env::set_var("SUPABASE_API_KEY", val);
106        }
107    }
108
109    #[test]
110    fn test_client_empty_url() {
111        let result = Supabase::new(Some(""), Some("key"), None);
112        assert!(result.is_err());
113    }
114
115    #[test]
116    fn test_client_empty_api_key() {
117        let result = Supabase::new(Some("https://example.supabase.co"), Some(""), None);
118        assert!(result.is_err());
119    }
120
121    #[test]
122    fn test_set_bearer_token() {
123        let mut client = Supabase::new(
124            Some("https://example.supabase.co"),
125            Some("test-key"),
126            None,
127        )
128        .unwrap();
129        client.set_bearer_token("my-token");
130        assert_eq!(client.bearer_token, Some("my-token".to_string()));
131    }
132}