use std::future::Future;
use std::sync::Arc;
use crate::error::{Error, Result};
use crate::files::{FileDownload, UploadFile};
use crate::models::{
BatchResult, Bill, BillDetail, BillRecord, BillsStats, BillsSummary, Category, DocumentDetail,
DocumentListItem, ExtractResult, Extraction, HeldEmail, ReviewQueueItem, ReviewQueueListItem,
StatsOverview, Usage, WebhookEndpointList, WebhookEndpointWithSecret,
};
use crate::params::{
BillsStatsParams, BillsSummaryParams, CreateWebhookEndpoint, ExtractOptions, ListBillsParams,
ListDocumentsParams, ListReviewQueueParams, ReviewResolution, WaitOptions,
};
use crate::{ClientBuilder, ExtractedDocument};
#[derive(Debug, Clone)]
pub struct Client {
inner: crate::Client,
runtime: Arc<tokio::runtime::Runtime>,
}
impl ClientBuilder {
pub fn build_blocking(self) -> Result<Client> {
Client::with_client(self.build()?)
}
}
impl Client {
pub fn new(api_key: impl Into<String>) -> Result<Self> {
Client::with_client(crate::Client::new(api_key)?)
}
pub fn from_env() -> Result<Self> {
Client::with_client(crate::Client::from_env()?)
}
pub fn with_client(client: crate::Client) -> Result<Self> {
let runtime = tokio::runtime::Builder::new_current_thread()
.enable_all()
.build()
.map_err(|e| {
Error::invalid_argument(format!(
"Could not start the blocking client's runtime: {e}"
))
.with_source(e)
})?;
Ok(Client {
inner: client,
runtime: Arc::new(runtime),
})
}
pub fn as_async(&self) -> &crate::Client {
&self.inner
}
fn run<F: Future>(&self, future: F) -> F::Output {
self.runtime.block_on(future)
}
pub fn extract(&self, file: UploadFile, options: ExtractOptions) -> Result<ExtractResult> {
self.run(self.inner.extract(file, options))
}
pub fn extract_batch(
&self,
files: impl IntoIterator<Item = UploadFile>,
) -> Result<BatchResult> {
self.run(self.inner.extract_batch(files))
}
pub fn list_documents(&self, params: ListDocumentsParams) -> Result<Vec<DocumentListItem>> {
self.run(self.inner.list_documents(params))
}
pub fn get_document(&self, id: &str) -> Result<DocumentDetail> {
self.run(self.inner.get_document(id))
}
pub fn get_document_file(&self, id: &str) -> Result<FileDownload> {
self.run(self.inner.get_document_file(id))
}
pub fn wait_for_extraction(
&self,
document_id: &str,
options: WaitOptions,
) -> Result<Extraction> {
self.run(self.inner.wait_for_extraction(document_id, options))
}
pub fn extract_and_wait(
&self,
file: UploadFile,
options: WaitOptions,
) -> Result<ExtractedDocument> {
self.run(self.inner.extract_and_wait(file, options))
}
pub fn list_review_queue(
&self,
params: ListReviewQueueParams,
) -> Result<Vec<ReviewQueueListItem>> {
self.run(self.inner.list_review_queue(params))
}
pub fn resolve_review_item(
&self,
id: &str,
resolution: ReviewResolution,
) -> Result<ReviewQueueItem> {
self.run(self.inner.resolve_review_item(id, resolution))
}
pub fn list_categories(&self) -> Result<Vec<Category>> {
self.run(self.inner.list_categories())
}
pub fn get_usage(&self) -> Result<Usage> {
self.run(self.inner.get_usage())
}
pub fn get_stats(&self) -> Result<StatsOverview> {
self.run(self.inner.get_stats())
}
pub fn list_webhook_endpoints(&self) -> Result<WebhookEndpointList> {
self.run(self.inner.list_webhook_endpoints())
}
pub fn create_webhook_endpoint(
&self,
endpoint: CreateWebhookEndpoint,
) -> Result<WebhookEndpointWithSecret> {
self.run(self.inner.create_webhook_endpoint(endpoint))
}
pub fn delete_webhook_endpoint(&self, id: &str) -> Result<()> {
self.run(self.inner.delete_webhook_endpoint(id))
}
pub fn bills(&self) -> Bills<'_> {
Bills { client: self }
}
pub fn held_emails(&self) -> HeldEmails<'_> {
HeldEmails { client: self }
}
}
#[derive(Debug, Clone, Copy)]
pub struct Bills<'a> {
client: &'a Client,
}
impl Bills<'_> {
pub fn list(&self, params: ListBillsParams) -> Result<Vec<Bill>> {
self.client.run(self.client.inner.bills().list(params))
}
pub fn get(&self, id: &str) -> Result<BillDetail> {
self.client.run(self.client.inner.bills().get(id))
}
pub fn get_file(&self, id: &str) -> Result<FileDownload> {
self.client.run(self.client.inner.bills().get_file(id))
}
pub fn summary(&self, params: BillsSummaryParams) -> Result<BillsSummary> {
self.client.run(self.client.inner.bills().summary(params))
}
pub fn stats(&self, params: BillsStatsParams) -> Result<BillsStats> {
self.client.run(self.client.inner.bills().stats(params))
}
pub fn mark_paid(&self, id: &str) -> Result<BillRecord> {
self.client.run(self.client.inner.bills().mark_paid(id))
}
pub fn mark_unpaid(&self, id: &str) -> Result<BillRecord> {
self.client.run(self.client.inner.bills().mark_unpaid(id))
}
}
#[derive(Debug, Clone, Copy)]
pub struct HeldEmails<'a> {
client: &'a Client,
}
impl HeldEmails<'_> {
pub fn list(&self) -> Result<Vec<HeldEmail>> {
self.client.run(self.client.inner.held_emails().list())
}
}