reasoninglayer 1.0.3

Rust client SDK for the Reasoning Layer API
Documentation
//! Term (record) CRUD operations.

use crate::error::Error;
use crate::http::HttpClient;
use crate::types::common::RequestOptions;
use crate::types::query::TermListResponse;
use crate::types::terms::{
    BulkAddTermsRequest, BulkAddTermsResponse, ClearTermsResponse, CreateTermRequest, TermResponse,
    UpdateTermRequest,
};

/// Resource client for term CRUD operations.
///
/// Terms use the tagged [`ValueDto`](crate::types::values::ValueDto) format.
/// [`create_term`](Self::create_term) and friends accept features as `BTreeMap<String, ValueDto>` —
/// use [`Value`](crate::Value) builders or plain `.into()` conversions to populate the map.
#[derive(Debug, Clone)]
pub struct TermsClient {
    http: HttpClient,
}

impl TermsClient {
    pub(crate) fn new(http: HttpClient) -> Self {
        Self { http }
    }

    /// Create a new term.
    pub async fn create_term(
        &self,
        request: CreateTermRequest,
        options: Option<&RequestOptions>,
    ) -> Result<TermResponse, Error> {
        self.http.post("/terms", &request, options).await
    }

    /// Get a term by ID.
    pub async fn get_term(
        &self,
        term_id: &str,
        options: Option<&RequestOptions>,
    ) -> Result<TermResponse, Error> {
        let path = format!("/terms/{}", encode(term_id));
        self.http.get(&path, None, options).await
    }

    /// Update an existing term.
    pub async fn update_term(
        &self,
        term_id: &str,
        request: UpdateTermRequest,
        options: Option<&RequestOptions>,
    ) -> Result<TermResponse, Error> {
        let path = format!("/terms/{}", encode(term_id));
        self.http.put(&path, &request, options).await
    }

    /// Delete a term by ID.
    pub async fn delete_term(
        &self,
        term_id: &str,
        options: Option<&RequestOptions>,
    ) -> Result<(), Error> {
        let path = format!("/terms/{}", encode(term_id));
        let _: serde_json::Value = self.http.delete(&path, None, options).await?;
        Ok(())
    }

    /// Check if a term exists.
    ///
    /// Returns `Ok(false)` on 404; any other error is propagated.
    pub async fn term_exists(
        &self,
        term_id: &str,
        options: Option<&RequestOptions>,
    ) -> Result<bool, Error> {
        let path = format!("/terms/{}/exists", encode(term_id));
        match self
            .http
            .get::<serde_json::Value>(&path, None, options)
            .await
        {
            Ok(_) => Ok(true),
            Err(Error::Api(e)) if e.status.as_u16() == 404 => Ok(false),
            Err(e) => Err(e),
        }
    }

    /// Bulk-create terms.
    pub async fn bulk_create_terms(
        &self,
        request: BulkAddTermsRequest,
        options: Option<&RequestOptions>,
    ) -> Result<BulkAddTermsResponse, Error> {
        self.http.post("/terms/bulk", &request, options).await
    }

    /// List all terms for the authenticated tenant.
    pub async fn list_terms(
        &self,
        options: Option<&RequestOptions>,
    ) -> Result<TermListResponse, Error> {
        self.http.get("/terms", None, options).await
    }

    /// Clear all terms for the authenticated tenant.
    pub async fn clear_terms(
        &self,
        options: Option<&RequestOptions>,
    ) -> Result<ClearTermsResponse, Error> {
        self.http.delete("/terms", None, options).await
    }

    /// Alias for [`TermsClient::bulk_create_terms`].
    pub async fn create_many(
        &self,
        request: BulkAddTermsRequest,
        options: Option<&RequestOptions>,
    ) -> Result<BulkAddTermsResponse, Error> {
        self.bulk_create_terms(request, options).await
    }
}

fn encode(segment: &str) -> String {
    url::form_urlencoded::byte_serialize(segment.as_bytes()).collect()
}