front_api/
lib.rs

1//! A fully generated & opinionated API client for the Front API.
2//!
3//! [![docs.rs](https://docs.rs/front-api/badge.svg)](https://docs.rs/front-api)
4//!
5//! ## API Details
6//!
7//!
8//!
9//!
10//!
11//! ### Contact
12//!
13//!
14//! | name | email |
15//! |----|----|
16//! | Front Platform | api@frontapp.com |
17//!
18//!
19//!
20//! ## Client Details
21//!
22//!
23//!
24//! The documentation for the crate is generated
25//! along with the code to make this library easy to use.
26//!
27//!
28//! To install the library, add the following to your `Cargo.toml` file.
29//!
30//! ```toml
31//! [dependencies]
32//! front-api = "0.0.2"
33//! ```
34//!
35//! ## Basic example
36//!
37//! Typical use will require intializing a `Client`. This requires
38//! a user agent string and set of credentials.
39//!
40//! ```rust,no_run
41//! use front_api::Client;
42//!
43//! let client = Client::new(String::from("api-key"));
44//! ```
45//!
46//! Alternatively, the library can search for most of the variables required for
47//! the client in the environment:
48//!
49//! - `FRONT_API_TOKEN`
50//!
51//! And then you can create a client from the environment.
52//!
53//! ```rust,no_run
54//! use front_api::Client;
55//!
56//! let client = Client::new_from_env();
57//! ```
58#![allow(missing_docs)]
59#![allow(clippy::needless_lifetimes)]
60#![cfg_attr(docsrs, feature(doc_cfg))]
61
62#[doc(hidden)]
63pub mod accounts;
64pub mod analytics;
65pub mod attachments;
66pub mod channels;
67pub mod comments;
68pub mod contact_groups;
69pub mod contact_handles;
70pub mod contact_notes;
71pub mod contacts;
72pub mod conversations;
73pub mod custom_fields;
74pub mod drafts;
75pub mod events;
76pub mod inboxes;
77pub mod links;
78pub mod message_template_folders;
79pub mod message_templates;
80pub mod messages;
81pub mod rules;
82pub mod shifts;
83pub mod signatures;
84pub mod tags;
85pub mod teammates;
86pub mod teams;
87#[cfg(test)]
88mod tests;
89pub mod token_identity;
90pub mod types;
91
92use std::env;
93
94static APP_USER_AGENT: &str = concat!(env!("CARGO_PKG_NAME"), ".rs/", env!("CARGO_PKG_VERSION"),);
95
96/// Entrypoint for interacting with the API client.
97#[derive(Clone, Debug)]
98pub struct Client {
99    token: String,
100    base_url: String,
101
102    client: reqwest_middleware::ClientWithMiddleware,
103}
104
105impl Client {
106    /// Create a new Client struct. It takes a type that can convert into
107    /// an &str (`String` or `Vec<u8>` for example). As long as the function is
108    /// given a valid API key your requests will work.
109    #[tracing::instrument]
110    pub fn new<T>(token: T) -> Self
111    where
112        T: ToString + std::fmt::Debug,
113    {
114        // Retry up to 3 times with increasing intervals between attempts.
115        let retry_policy =
116            reqwest_retry::policies::ExponentialBackoff::builder().build_with_max_retries(3);
117        let client = reqwest::Client::builder()
118            .user_agent(APP_USER_AGENT)
119            .build();
120        match client {
121            Ok(c) => {
122                let client = reqwest_middleware::ClientBuilder::new(c)
123                    // Trace HTTP requests. See the tracing crate to make use of these traces.
124                    .with(reqwest_tracing::TracingMiddleware::default())
125                    // Retry failed requests.
126                    .with(reqwest_conditional_middleware::ConditionalMiddleware::new(
127                        reqwest_retry::RetryTransientMiddleware::new_with_policy(retry_policy),
128                        |req: &reqwest::Request| req.try_clone().is_some(),
129                    ))
130                    .build();
131
132                Client {
133                    token: token.to_string(),
134                    base_url: "https://api2.frontapp.com".to_string(),
135
136                    client,
137                }
138            }
139            Err(e) => panic!("creating reqwest client failed: {:?}", e),
140        }
141    }
142
143    /// Set the base URL for the client to something other than the default: <https://api2.frontapp.com>.
144    #[tracing::instrument]
145    pub fn set_base_url<H>(&mut self, base_url: H)
146    where
147        H: Into<String> + std::fmt::Display + std::fmt::Debug,
148    {
149        self.base_url = base_url.to_string().trim_end_matches('/').to_string();
150    }
151
152    /// Create a new Client struct from the environment variable: `FRONT_API_TOKEN`.
153    #[tracing::instrument]
154    pub fn new_from_env() -> Self {
155        let token = env::var("FRONT_API_TOKEN").expect("must set FRONT_API_TOKEN");
156
157        Client::new(token)
158    }
159
160    /// Create a raw request to our API.
161    #[tracing::instrument]
162    pub async fn request_raw(
163        &self,
164        method: reqwest::Method,
165        uri: &str,
166        body: Option<reqwest::Body>,
167    ) -> anyhow::Result<reqwest_middleware::RequestBuilder> {
168        let u = if uri.starts_with("https://") || uri.starts_with("http://") {
169            uri.to_string()
170        } else {
171            format!("{}/{}", self.base_url, uri.trim_start_matches('/'))
172        };
173
174        let mut req = self.client.request(method, &u);
175
176        // Add in our authentication.
177        req = req.bearer_auth(&self.token);
178
179        // Set the default headers.
180        req = req.header(
181            reqwest::header::ACCEPT,
182            reqwest::header::HeaderValue::from_static("application/json"),
183        );
184        req = req.header(
185            reqwest::header::CONTENT_TYPE,
186            reqwest::header::HeaderValue::from_static("application/json"),
187        );
188
189        if let Some(body) = body {
190            req = req.body(body);
191        }
192
193        Ok(req)
194    }
195
196    /// Return a reference to an interface that provides access to Accounts operations.
197    pub fn accounts(&self) -> accounts::Accounts {
198        accounts::Accounts::new(self.clone())
199    }
200
201    /// Return a reference to an interface that provides access to Events operations.
202    pub fn events(&self) -> events::Events {
203        events::Events::new(self.clone())
204    }
205
206    /// Return a reference to an interface that provides access to Analytics operations.
207    pub fn analytics(&self) -> analytics::Analytics {
208        analytics::Analytics::new(self.clone())
209    }
210
211    /// Return a reference to an interface that provides access to Attachments operations.
212    pub fn attachments(&self) -> attachments::Attachments {
213        attachments::Attachments::new(self.clone())
214    }
215
216    /// Return a reference to an interface that provides access to Token Identity operations.
217    pub fn token_identity(&self) -> token_identity::TokenIdentity {
218        token_identity::TokenIdentity::new(self.clone())
219    }
220
221    /// Return a reference to an interface that provides access to Message Template Folders operations.
222    pub fn message_template_folders(&self) -> message_template_folders::MessageTemplateFolders {
223        message_template_folders::MessageTemplateFolders::new(self.clone())
224    }
225
226    /// Return a reference to an interface that provides access to Message Templates operations.
227    pub fn message_templates(&self) -> message_templates::MessageTemplates {
228        message_templates::MessageTemplates::new(self.clone())
229    }
230
231    /// Return a reference to an interface that provides access to Contact Groups operations.
232    pub fn contact_groups(&self) -> contact_groups::ContactGroups {
233        contact_groups::ContactGroups::new(self.clone())
234    }
235
236    /// Return a reference to an interface that provides access to Contacts operations.
237    pub fn contacts(&self) -> contacts::Contacts {
238        contacts::Contacts::new(self.clone())
239    }
240
241    /// Return a reference to an interface that provides access to Contact Handles operations.
242    pub fn contact_handles(&self) -> contact_handles::ContactHandles {
243        contact_handles::ContactHandles::new(self.clone())
244    }
245
246    /// Return a reference to an interface that provides access to Contact Notes operations.
247    pub fn contact_notes(&self) -> contact_notes::ContactNotes {
248        contact_notes::ContactNotes::new(self.clone())
249    }
250
251    /// Return a reference to an interface that provides access to Channels operations.
252    pub fn channels(&self) -> channels::Channels {
253        channels::Channels::new(self.clone())
254    }
255
256    /// Return a reference to an interface that provides access to Inboxes operations.
257    pub fn inboxes(&self) -> inboxes::Inboxes {
258        inboxes::Inboxes::new(self.clone())
259    }
260
261    /// Return a reference to an interface that provides access to Comments operations.
262    pub fn comments(&self) -> comments::Comments {
263        comments::Comments::new(self.clone())
264    }
265
266    /// Return a reference to an interface that provides access to Conversations operations.
267    pub fn conversations(&self) -> conversations::Conversations {
268        conversations::Conversations::new(self.clone())
269    }
270
271    /// Return a reference to an interface that provides access to Messages operations.
272    pub fn messages(&self) -> messages::Messages {
273        messages::Messages::new(self.clone())
274    }
275
276    /// Return a reference to an interface that provides access to Custom Fields operations.
277    pub fn custom_fields(&self) -> custom_fields::CustomFields {
278        custom_fields::CustomFields::new(self.clone())
279    }
280
281    /// Return a reference to an interface that provides access to Drafts operations.
282    pub fn drafts(&self) -> drafts::Drafts {
283        drafts::Drafts::new(self.clone())
284    }
285
286    /// Return a reference to an interface that provides access to Rules operations.
287    pub fn rules(&self) -> rules::Rules {
288        rules::Rules::new(self.clone())
289    }
290
291    /// Return a reference to an interface that provides access to Shifts operations.
292    pub fn shifts(&self) -> shifts::Shifts {
293        shifts::Shifts::new(self.clone())
294    }
295
296    /// Return a reference to an interface that provides access to Signatures operations.
297    pub fn signatures(&self) -> signatures::Signatures {
298        signatures::Signatures::new(self.clone())
299    }
300
301    /// Return a reference to an interface that provides access to Tags operations.
302    pub fn tags(&self) -> tags::Tags {
303        tags::Tags::new(self.clone())
304    }
305
306    /// Return a reference to an interface that provides access to Teams operations.
307    pub fn teams(&self) -> teams::Teams {
308        teams::Teams::new(self.clone())
309    }
310
311    /// Return a reference to an interface that provides access to Teammates operations.
312    pub fn teammates(&self) -> teammates::Teammates {
313        teammates::Teammates::new(self.clone())
314    }
315
316    /// Return a reference to an interface that provides access to Links operations.
317    pub fn links(&self) -> links::Links {
318        links::Links::new(self.clone())
319    }
320}