Skip to main content

mesa_dev/client/
mod.rs

1//! Ergonomic client for the Mesa API.
2//!
3//! Provides a directory-style navigation pattern:
4//!
5//! ```rust,no_run
6//! use mesa_dev::MesaClient;
7//! use futures::TryStreamExt;
8//!
9//! # async fn example() -> Result<(), Box<dyn std::error::Error>> {
10//! let client = MesaClient::builder().build();
11//! let repos: Vec<_> = client.org("my-org").repos().list(None).try_collect().await?;
12//! let branches: Vec<_> = client.org("my-org").repos().at("my-repo").branches().list(None).try_collect().await?;
13//! # Ok(())
14//! # }
15//! ```
16
17mod analytics;
18mod api_keys;
19mod branches;
20mod commits;
21mod content;
22mod diff;
23mod org;
24mod repo;
25mod repos;
26mod sync;
27mod webhooks;
28
29mod pagination;
30
31pub use analytics::AnalyticsClient;
32pub use api_keys::ApiKeysClient;
33pub use branches::BranchesClient;
34pub use commits::CommitsClient;
35pub use content::ContentClient;
36pub use diff::DiffClient;
37pub use org::OrgClient;
38pub use repo::RepoClient;
39pub use repos::ReposClient;
40pub use sync::SyncClient;
41pub use webhooks::WebhooksClient;
42
43use crate::low_level::apis::configuration::Configuration;
44
45/// Builder for configuring and constructing a [`MesaClient`].
46#[derive(Clone, Debug, Default)]
47pub struct MesaClientBuilder {
48    base_path: Option<String>,
49    user_agent: Option<String>,
50    client: Option<reqwest_middleware::ClientWithMiddleware>,
51    api_key: Option<String>,
52}
53
54impl MesaClientBuilder {
55    /// Attach a non-default base URL for the API (e.g. for testing against a staging environment).
56    #[must_use]
57    pub fn with_base_path(mut self, base_path: impl Into<String>) -> Self {
58        self.base_path = Some(base_path.into());
59        self
60    }
61
62    /// Attach a custom User-Agent header to all requests.
63    #[must_use]
64    pub fn with_user_agent(mut self, user_agent: impl Into<String>) -> Self {
65        self.user_agent = Some(user_agent.into());
66        self
67    }
68
69    /// Attach a custom HTTP client (e.g. with additional middleware or custom timeout settings).
70    #[must_use]
71    pub fn with_client(mut self, client: reqwest_middleware::ClientWithMiddleware) -> Self {
72        self.client = Some(client);
73        self
74    }
75
76    /// Attach an API key for authentication.
77    #[must_use]
78    pub fn with_api_key(mut self, api_key: impl Into<String>) -> Self {
79        self.api_key = Some(api_key.into());
80        self
81    }
82
83    /// Finalize the builder and construct a [`MesaClient`].
84    #[must_use]
85    pub fn build(self) -> MesaClient {
86        let mut config = Configuration::default();
87
88        if let Some(base_path) = self.base_path {
89            config.base_path = base_path;
90        }
91
92        config.user_agent = self.user_agent.clone().or(Some(Self::default_user_agent()));
93        if let Some(client) = self.client {
94            config.client = client;
95        }
96
97        if let Some(api_key) = self.api_key {
98            config.bearer_access_token = Some(api_key);
99        }
100
101        MesaClient { config }
102    }
103
104    fn default_user_agent() -> String {
105        format!(
106            "mesa-dev/{} (rust/{})",
107            env!("CARGO_PKG_VERSION"),
108            env!("MESA_RUSTC_VERSION"),
109        )
110    }
111}
112
113/// Top-level Mesa API client.
114///
115/// Create one with [`MesaClient::builder`] or [`MesaClient::from_configuration`]
116/// and navigate to sub-resources with [`MesaClient::org`].
117#[derive(Clone, Debug)]
118pub struct MesaClient {
119    config: Configuration,
120}
121
122impl MesaClient {
123    /// Create a new builder with default configuration.
124    #[must_use]
125    pub fn builder() -> MesaClientBuilder {
126        MesaClientBuilder::default()
127    }
128
129    /// Create a new client from an existing [`Configuration`].
130    #[must_use]
131    pub fn from_configuration(config: Configuration) -> Self {
132        Self { config }
133    }
134
135    /// Navigate to an organization.
136    #[must_use]
137    pub fn org<'a>(&'a self, name: &'a str) -> OrgClient<'a> {
138        OrgClient {
139            config: &self.config,
140            org: name,
141        }
142    }
143}