142 lines
4.4 KiB
Rust
142 lines
4.4 KiB
Rust
use std::fmt::Debug;
|
|
|
|
use serde::Serialize;
|
|
|
|
use crate::{
|
|
create_records::CreateRecordsQueryBuilder, list_bases::ListBasesQueryBuilder,
|
|
list_records::ListRecordsQueryBuilder,
|
|
};
|
|
|
|
const DEFAULT_API_ROOT: &str = "https://api.airtable.com";
|
|
|
|
#[derive(Clone)]
|
|
pub struct Client {
|
|
// TODO: Does API root need to be customizable per client, e.g. for on-prem
|
|
// enterprise deployments, or is that not a thing?
|
|
api_root: String,
|
|
client: reqwest::Client,
|
|
token: String,
|
|
}
|
|
|
|
impl Client {
|
|
pub fn new_from_access_token(token: &str) -> Result<Self, reqwest::Error> {
|
|
Ok(Self {
|
|
api_root: DEFAULT_API_ROOT.to_owned(),
|
|
client: reqwest::ClientBuilder::default()
|
|
.https_only(true)
|
|
.build()
|
|
.expect("reqwest client is always built with the same configuration here"),
|
|
token: token.to_owned(),
|
|
})
|
|
}
|
|
|
|
/// Creates multiple records. Note that table names and table ids can be
|
|
/// used interchangeably. We recommend using table IDs so you don't need
|
|
/// to modify your API request when your table name changes.
|
|
///
|
|
/// Your request body should include an array of up to 10 record objects.
|
|
///
|
|
/// Returns a unique array of the newly created record ids if the call
|
|
/// succeeds.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ```no_run
|
|
/// client
|
|
/// .create_records([
|
|
/// HashMap<&str, &str>::from([
|
|
/// ("name", "Steal Improbability Drive"),
|
|
/// ("notes", "Just for fun, no other reason."),
|
|
/// ("status", "In progress"),
|
|
/// ]),
|
|
/// ])
|
|
/// .with_base_id("***".to_owned())
|
|
/// .with_table_id("***".to_owned())
|
|
/// .build()?
|
|
/// .execute()
|
|
/// .await?;
|
|
/// ```
|
|
pub fn create_records<I, T>(&self, records: I) -> CreateRecordsQueryBuilder<T>
|
|
where
|
|
T: Serialize,
|
|
I: IntoIterator<Item = T>,
|
|
{
|
|
CreateRecordsQueryBuilder::default()
|
|
.with_client(self.clone())
|
|
.with_records(records.into_iter().collect())
|
|
}
|
|
|
|
/// List the bases the token can access
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ## Consuming as Stream
|
|
///
|
|
/// ```no_run
|
|
/// use futures::prelude::*;
|
|
///
|
|
/// let mut base_stream = client
|
|
/// .list_bases()
|
|
/// .build()?
|
|
/// .stream_items();
|
|
///
|
|
/// while let Some(result) = base_stream.next().await {
|
|
/// dbg!(result?);
|
|
/// }
|
|
/// ```
|
|
pub fn list_bases(&self) -> ListBasesQueryBuilder {
|
|
ListBasesQueryBuilder::default().with_client(self.clone())
|
|
}
|
|
|
|
/// List records in a table. Note that table names and table ids can be used
|
|
/// interchangeably. We recommend using table IDs so you don't need to modify
|
|
/// your API request when your table name changes.
|
|
///
|
|
/// # Examples
|
|
///
|
|
/// ## Consuming as Stream
|
|
///
|
|
/// ```no_run
|
|
/// let mut rec_stream = client
|
|
/// .list_records()
|
|
/// .with_base_id("***")
|
|
/// .with_table_id("***")
|
|
/// .build()?
|
|
/// .stream_items::<HashMap<String, serde_json::Value>>();
|
|
///
|
|
/// while let Some(result) = rec_stream.next().await {
|
|
/// dbg!(rec?.fields);
|
|
/// }
|
|
/// ```
|
|
pub fn list_records(&self) -> ListRecordsQueryBuilder {
|
|
ListRecordsQueryBuilder::default().with_client(self.clone())
|
|
}
|
|
|
|
/// Constructs a RequestBuilder with URL "{self.api_root}/{path}" and the
|
|
/// Authorization header set to the correct bearer auth value.
|
|
pub(crate) fn get_path(&self, path: &str) -> reqwest::RequestBuilder {
|
|
let Self {
|
|
api_root, token, ..
|
|
} = self;
|
|
self.client
|
|
.get(format!("{api_root}/{path}"))
|
|
.header(reqwest::header::AUTHORIZATION, format!("Bearer {token}"))
|
|
}
|
|
|
|
/// Constructs a RequestBuilder with URL "{self.api_root}/{path}" and the
|
|
/// Authorization header set to the correct bearer auth value.
|
|
pub(crate) fn post_path(&self, path: &str) -> reqwest::RequestBuilder {
|
|
let Self {
|
|
api_root, token, ..
|
|
} = self;
|
|
self.client
|
|
.post(format!("{api_root}/{path}"))
|
|
.header(reqwest::header::AUTHORIZATION, format!("Bearer {token}"))
|
|
}
|
|
}
|
|
|
|
impl Debug for Client {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
write!(f, "ferrtable::Client {{ *** }}")
|
|
}
|
|
}
|