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