Skip to main content

busbar_sf_tooling/client/
apex.rs

1use busbar_sf_client::security::{soql, url as url_security};
2use tracing::instrument;
3
4use crate::error::{Error, ErrorKind, Result};
5use crate::types::*;
6
7impl super::ToolingClient {
8    // =========================================================================
9    // Apex Class Operations
10    // =========================================================================
11
12    /// Get all Apex classes in the org.
13    #[instrument(skip(self))]
14    pub async fn get_apex_classes(&self) -> Result<Vec<ApexClass>> {
15        self.query_all("SELECT Id, Name, Body, Status, IsValid, ApiVersion, NamespacePrefix, CreatedDate, LastModifiedDate FROM ApexClass")
16            .await
17    }
18
19    /// Get an Apex class by name.
20    #[instrument(skip(self))]
21    pub async fn get_apex_class_by_name(&self, name: &str) -> Result<Option<ApexClass>> {
22        let safe_name = soql::escape_string(name);
23        let soql = format!(
24            "SELECT Id, Name, Body, Status, IsValid, ApiVersion, NamespacePrefix, CreatedDate, LastModifiedDate FROM ApexClass WHERE Name = '{}'",
25            safe_name
26        );
27        let mut classes: Vec<ApexClass> = self.query_all(&soql).await?;
28        Ok(classes.pop())
29    }
30
31    /// Get an Apex class by ID.
32    #[instrument(skip(self))]
33    pub async fn get_apex_class(&self, id: &str) -> Result<ApexClass> {
34        if !url_security::is_valid_salesforce_id(id) {
35            return Err(Error::new(ErrorKind::Salesforce {
36                error_code: "INVALID_ID".to_string(),
37                message: "Invalid Salesforce ID format".to_string(),
38            }));
39        }
40        let path = format!("sobjects/ApexClass/{}", id);
41        self.client.tooling_get(&path).await.map_err(Into::into)
42    }
43
44    // =========================================================================
45    // Apex Trigger Operations
46    // =========================================================================
47
48    /// Get all Apex triggers in the org.
49    #[instrument(skip(self))]
50    pub async fn get_apex_triggers(&self) -> Result<Vec<ApexTrigger>> {
51        self.query_all(
52            "SELECT Id, Name, Body, Status, IsValid, ApiVersion, TableEnumOrId FROM ApexTrigger",
53        )
54        .await
55    }
56
57    /// Get an Apex trigger by name.
58    #[instrument(skip(self))]
59    pub async fn get_apex_trigger_by_name(&self, name: &str) -> Result<Option<ApexTrigger>> {
60        let safe_name = soql::escape_string(name);
61        let soql = format!(
62            "SELECT Id, Name, Body, Status, IsValid, ApiVersion, TableEnumOrId FROM ApexTrigger WHERE Name = '{}'",
63            safe_name
64        );
65        let mut triggers: Vec<ApexTrigger> = self.query_all(&soql).await?;
66        Ok(triggers.pop())
67    }
68}