use std::fmt::Debug;
use derive_builder::Builder;
use percent_encoding::{NON_ALPHANUMERIC, utf8_percent_encode};
use serde::{Deserialize, Serialize, de::DeserializeOwned};
use crate::{client::Client, errors::ExecutionError, types::AirtableRecord};
#[derive(Builder, Clone, Debug)]
#[builder(pattern = "owned", setter(prefix = "with"))]
pub struct CreateRecordsQuery<T>
where
T: Serialize,
{
base_id: String,
#[builder(vis = "pub(crate)")]
client: Client,
#[builder(vis = "pub(crate)")]
records: Vec<T>,
table_id: String,
}
#[derive(Clone, Deserialize)]
pub struct CreateRecordsResponse<T>
where
T: Clone + Debug + Serialize,
{
pub records: Vec<AirtableRecord<T>>,
pub details: Option<CreateRecordsDetails>,
}
#[derive(Clone, Debug, Deserialize)]
pub struct CreateRecordsDetails {
pub message: String,
pub reasons: Vec<String>,
}
impl<T> CreateRecordsQuery<T>
where
T: Clone + Debug + DeserializeOwned + Serialize,
{
pub async fn execute(self) -> Result<CreateRecordsResponse<T>, ExecutionError> {
#[derive(Serialize)]
struct Record<RT: Serialize> {
fields: RT,
}
#[derive(Serialize)]
struct RequestBody<RT: Serialize> {
records: Vec<Record<RT>>,
}
let base_id = utf8_percent_encode(&self.base_id, NON_ALPHANUMERIC).to_string();
let table_id = utf8_percent_encode(&self.table_id, NON_ALPHANUMERIC).to_string();
let http_resp = self
.client
.post_path(&format!("v0/{base_id}/{table_id}"))
.json(&RequestBody {
records: self
.records
.into_iter()
.map(|rec| Record { fields: rec })
.collect(),
})
.send()
.await?
.error_for_status()?;
let deserialized_resp: CreateRecordsResponse<T> = http_resp.json().await?;
Ok(deserialized_resp)
}
}