8 releases
0.3.2 | Aug 8, 2023 |
---|---|
0.3.1 | May 18, 2023 |
0.2.3 | Apr 24, 2023 |
0.2.2 | Mar 31, 2023 |
0.1.0 | Feb 2, 2023 |
#862 in Web programming
52 downloads per month
76KB
1.5K
SLoC
Rust Sync Force
Salesforce Client for Rust Sync. Support most Salesforce REST methods. Also supports Change Data Capture.
Rust async version is here https://github.com/tzmfreedom/rustforce
Usage
use rust_sync_force::{Client, Error};
use rust_sync_force::response::{QueryResponse, ErrorResponse};
use serde::Deserialize;
use std::env;
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct Account {
#[serde(rename = "attributes")]
attributes: Attribute,
id: String,
name: String,
}
#[derive(Deserialize, Debug)]
struct Attribute {
url: String,
#[serde(rename = "type")]
sobject_type: String,
}
fn main() -> Result<(), Error> {
let client_id = env::var("SFDC_CLIENT_ID").unwrap();
let client_secret = env::var("SFDC_CLIENT_SECRET").unwrap();
let username = env::var("SFDC_USERNAME").unwrap();
let password = env::var("SFDC_PASSWORD").unwrap();
let mut client = Client::new(client_id, client_secret);
client.login_with_credential(username, password)?;
let res: QueryResponse<Account> = client.query("SELECT Id, Name FROM Account WHERE id = '0012K00001drfGYQAY'".to_string())?;
println!("{:?}", res);
Ok(())
}
Authentication
Username Password Flow
let mut client = Client::new(client_id, client_secret);
client.login_with_credential(username, password)?;
[WIP]Authorization Code Grant
Refresh Token
let r = client.refresh("xxxx")?;
Query Records
let r: Result<QueryResponse<Account>, Error> = client.query("SELECT Id, Name FROM Account")?;
Query All Records
let r: Result<QueryResponse<Account>, Error> = client.query_all("SELECT Id, Name FROM Account")?;
Find By Id
let r: Result<Account, Error> = client.find_by_id("Account", "{sf_id}")?;
Insert a Record
let mut params = HashMap::new();
params.insert("Name", "hello rust");
let r = client.insert("Account", params)?;
println!("{:?}", r);
Insert multiple Records
let account1 = Account {
name: "account name1".into(),
attributes: Attribute { sobject_type: "Account".into() },
};
let account2 = Account {
name: "account name2".into(),
attributes: Attribute { sobject_type: "Account".into() },
};
let r = client.inserts(true, vec![account1, account2])?;
Update a Record
let r = client.update("Account", "{sobject_id}", params)?;
Update multiple Records
let account = Account {
id: "account_id".into(),
name: "new_name".into(),
attributes: Attribute { sobject_type: "Account".into() },
};
let r = client.updates(true, vec![account])?;
Upsert a Record
let r = client.upsert("Account", "external_key_name", "external_key_value", params)?;
Upsert multiple Records
let account = Account {
exkey: "external_key_id".into(),
name: "new_name".into(),
attributes: Attribute { sobject_type: "Account".into() },
};
let r = client.upserts(true, "Account", "ExKey__c", vec![account])?;
Delete a Record
let r = client.delete("Account", "{sobject_id}")?;
Delete multiple Records
let r = client.deletes(true, vec!["account_id".into()])?;
Describe Global
let r = client.describe_global()?;
Describe SObject
let r = client.describe("Account")?;
Versions
let versions = client.versions()?;
Search(SOSL)
let r = client.search("FIND {Rust}")?;
Change Data Capture - Streaming
let mut client = Client::new(client_id, client_secret);
client.login_with_credential(username, password)?;
let mut stream_client = rust_sync_force::stream::CometdClient::new(
client,
// listen to Account Change Event
vec!["/data/AccountChangeEvent".to_string()],
);
stream_client.init().expect("Could not init cometd client");
println!("Cometd client successfully initialized");
for response in stream_client.connect()? {
if let StreamResponse::Delivery(delivery) = response {
match serde_json::from_value::<SFMetadata>(delivery.data.clone()) {
Ok(data) => {
println!("Data: {:#?}", data);
// Here you should have your patterns matching your own objects
}
Err(err) => {
println!(
"SF delivery data could not be parsed: {:?}\nData:{:?}",
err, delivery
)
}
}
}
}
#[derive(Debug, Deserialize)]
pub struct SFChangeEventHeader {
pub commitNumber: usize,
pub commitUser: String,
pub sequenceNumber: usize,
pub entityName: String,
pub changeType: String,
pub commitTimestamp: usize,
pub recordIds: Vec<String>,
}
#[derive(Debug, Deserialize)]
pub struct SFPayload {
pub LastModifiedDate: String,
pub ChangeEventHeader: SFChangeEventHeader,
}
#[derive(Debug, Deserialize)]
pub struct SFMetadata {
pub schema: String,
pub payload: SFPayload,
}
Dependencies
~8–10MB
~182K SLoC