1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
use crate::grpc::BearerTokenInterceptor;

#[derive(Clone, Debug)]
pub struct SpiceDBClient {
    #[cfg(feature = "schema")]
    schema_service_client: crate::schema::Client,
    #[cfg(feature = "permission")]
    permission_service_client: crate::permission::PermissionServiceClient,
}

impl SpiceDBClient {
    /// Reads the following env variables:
    /// - `ZED_TOKEN`
    /// - `ZED_ENDPOINT`
    pub async fn from_env() -> anyhow::Result<Self> {
        let token = std::env::var("ZED_TOKEN")?;
        let addr = std::env::var("ZED_ENDPOINT")?;
        Self::new(addr, token).await
    }

    pub async fn new(addr: impl Into<String>, token: impl AsRef<str>) -> anyhow::Result<Self> {
        let token = format!("Bearer {}", token.as_ref()).parse()?;
        let interceptor = BearerTokenInterceptor::new(token);
        let channel = tonic::transport::Channel::from_shared(addr.into())?
            .connect()
            .await?;
        Ok(SpiceDBClient {
            #[cfg(feature = "schema")]
            schema_service_client: crate::schema::Client::new(channel.clone(), interceptor.clone()),
            #[cfg(feature = "permission")]
            permission_service_client: crate::permission::PermissionServiceClient::new(
                channel.clone(),
                interceptor,
            ),
        })
    }

    pub fn leak(self) -> &'static Self {
        Box::leak(Box::new(self))
    }

    #[cfg(feature = "schema")]
    #[inline]
    pub fn schema_client(&self) -> &crate::schema::Client {
        &self.schema_service_client
    }

    #[cfg(feature = "schema")]
    pub fn into_schema_client(self) -> crate::schema::Client {
        self.schema_service_client
    }

    #[cfg(feature = "permission")]
    #[inline]
    pub fn permission_client(&self) -> &crate::permission::PermissionServiceClient {
        &self.permission_service_client
    }

    #[cfg(feature = "permission")]
    pub fn into_permission_client(self) -> crate::permission::PermissionServiceClient {
        self.permission_service_client
    }
}