Skip to main content

MetadataClient

Struct MetadataClient 

Source
pub struct MetadataClient { /* private fields */ }
Expand description

The Metadata API client.

Holds an HTTP client, an AuthSession for credentials, the API version to target, and a RetryPolicy for transient-failure handling. Cheap to clone — the auth session is Arc-shared and the HTTP client is internally reference-counted.

Implementations§

Source§

impl MetadataClient

Source

pub async fn create_metadata<S: AsRef<str>>( &self, type_name: &str, components: &[S], ) -> MetadataResult<Vec<SaveResult>>

Create one or more metadata components synchronously.

All components must be of the same type_name. Each entry in components is the inner XML of one <metadata> element — the SDK wraps each in <metadata xsi:type="met:{type_name}">…</metadata> and handles the SOAP envelope. Inside the wrapper, the metadata namespace is the default, so caller XML can use bare element names like <fullName>Foo</fullName>.

let class = r#"
    <fullName>MyClass</fullName>
    <apiVersion>66.0</apiVersion>
    <status>Active</status>
    <content>cHVibGljIGNsYXNzIE15Q2xhc3Mge30=</content>
"#;
let results: Vec<SaveResult> = md.create_metadata("ApexClass", &[class]).await?;
for r in &results {
    assert!(r.success, "create failed: {:?}", r.errors);
}

Returns one SaveResult per component. Partial success is possible — inspect each entry’s success field and per-entry errors.

Source

pub async fn update_metadata<S: AsRef<str>>( &self, type_name: &str, components: &[S], ) -> MetadataResult<Vec<SaveResult>>

Update one or more existing metadata components.

Same input shape as Self::create_metadata — each component’s <fullName> identifies which existing component to update. Returns one SaveResult per component.

Source

pub async fn upsert_metadata<S: AsRef<str>>( &self, type_name: &str, components: &[S], ) -> MetadataResult<Vec<UpsertResult>>

Create or update one or more metadata components.

Same input shape as Self::create_metadata. The returned UpsertResult::created flag distinguishes per-component inserts (true) from updates (false). Available in API v31+.

Source

pub async fn delete_metadata<S: AsRef<str>>( &self, type_name: &str, full_names: &[S], ) -> MetadataResult<Vec<DeleteResult>>

Delete one or more metadata components.

Returns one DeleteResult per full_names entry. Partial success is possible — inspect each entry.

Source

pub async fn read_metadata<T, S>( &self, type_name: &str, full_names: &[S], ) -> MetadataResult<Vec<T>>
where T: DeserializeOwned, S: AsRef<str>,

Read one or more metadata components synchronously.

The caller supplies a typed T: Deserialize shape that maps over one <records> element. Component XML uses the metadata namespace as default on the wire, so quick-xml’s serde deserialize sees field names like fullName, apiVersion, status, etc.

#[derive(Deserialize)]
#[serde(rename_all = "camelCase")]
struct ApexClassRecord {
    full_name: String,
    api_version: Option<String>,
    status: Option<String>,
    content: Option<String>,
}

let classes: Vec<ApexClassRecord> = md
    .read_metadata::<ApexClassRecord, _>("ApexClass", &["Foo", "Bar"])
    .await?;
Source

pub async fn rename_metadata( &self, type_name: &str, old_full_name: &str, new_full_name: &str, ) -> MetadataResult<SaveResult>

Rename a single metadata component.

Returns a single SaveResult — unlike the array-returning CRUD calls, renameMetadata takes one component at a time.

Source§

impl MetadataClient

Source

pub async fn deploy( &self, zip: Bytes, options: DeployOptions, ) -> MetadataResult<AsyncResult>

Starts a metadata deployment.

zip is the raw bytes of the deployment zip (containing package.xml plus the component files). The SDK base64-encodes it on the wire — pass the unencoded bytes.

Returns an AsyncResult whose id is the deployment job ID; use Self::check_deploy_status or Self::wait_for_deploy to follow its progress.

Source

pub async fn check_deploy_status( &self, deploy_id: &str, include_details: bool, ) -> MetadataResult<DeployResult>

Fetches the current status of a deployment.

include_details controls whether the response includes per-component success/failure entries and Apex test results. Costs extra bandwidth, but is required for any meaningful post-mortem on a failed deploy.

Source

pub async fn cancel_deploy( &self, deploy_id: &str, ) -> MetadataResult<CancelDeployResult>

Requests cancellation of an in-progress deployment.

Returns immediately. If the deployment was still queued, it’s canceled synchronously (done == true in the result). If it had started, the cancellation is processed asynchronously — check_deploy_status continues to return Canceling until the server transitions it to Canceled.

In API v65+, deployments that have entered FinalizingDeploy can’t be canceled.

Source

pub async fn deploy_recent_validation( &self, validation_id: &str, ) -> MetadataResult<String>

Quick-deploys a recently-validated deployment without re-running tests.

validation_id is the deploy ID returned by an earlier deploy() call that was run with DeployOptions::check_only set to true and finished successfully within the last 10 days.

Returns the new deployment job ID — use Self::check_deploy_status or Self::wait_for_deploy to follow it.

Source

pub async fn retrieve( &self, request: RetrieveRequest, ) -> MetadataResult<AsyncResult>

Starts a metadata retrieval.

Returns an AsyncResult whose id is the retrieve job ID; use Self::check_retrieve_status or Self::wait_for_retrieve to follow it. The retrieved zip bytes are returned as part of the RetrieveResult.

Source

pub async fn check_retrieve_status( &self, retrieve_id: &str, include_zip: bool, ) -> MetadataResult<RetrieveResult>

Fetches the current status of a retrieval.

include_zip controls whether the response embeds the base64-encoded zip bytes. The server populates that field only when the retrieve has succeeded; intermediate polls return zip_file: None regardless of this flag. Passing include_zip == true throughout polling is the simplest pattern and what Self::wait_for_retrieve does.

Source

pub async fn wait_for_deploy( &self, deploy_id: &str, ) -> MetadataResult<DeployResult>

Polls Self::check_deploy_status until done == true or the configured timeout fires.

Uses WaitConfig::default() — 2 s initial backoff doubling to a 30 s cap, no timeout. For CI-friendly timeouts, use Self::wait_for_deploy_with with WaitConfig::with_timeout.

DeployResult::details is populated best-effort: it comes from one final include_details: true fetch after the deploy reaches a terminal state, and if that follow-up call fails the terminal result is returned with details: None rather than discarding a completed deploy’s outcome behind an error.

Source

pub async fn wait_for_deploy_with( &self, deploy_id: &str, config: WaitConfig, ) -> MetadataResult<DeployResult>

Polling form with a configurable WaitConfig.

Source

pub async fn wait_for_retrieve( &self, retrieve_id: &str, ) -> MetadataResult<RetrieveResult>

Polls Self::check_retrieve_status until done == true or the configured timeout fires. The returned RetrieveResult has the zip bytes populated when the retrieve succeeded.

Source

pub async fn wait_for_retrieve_with( &self, retrieve_id: &str, config: WaitConfig, ) -> MetadataResult<RetrieveResult>

Polling form with a configurable WaitConfig.

Source§

impl MetadataClient

Source

pub async fn list_metadata( &self, queries: Vec<ListMetadataQuery>, as_of_version: &str, ) -> MetadataResult<Vec<FileProperties>>

Enumerate metadata components of one or more types.

Each ListMetadataQuery picks one metadata type (and optionally a folder for folder-based types). The Salesforce server limits this to 3 queries per call — pass more and we return MetadataError::InvalidArgument before hitting the wire. For broader enumeration, batch into multiple calls.

as_of_version controls the API version used to evaluate the queries (e.g. "66.0"); this matters when types/fields are added or removed across releases. Pass Self::api_version to use the client’s configured version.

Returns Vec<FileProperties> — one entry per matched component. Empty when nothing matches.

Source

pub async fn describe_metadata( &self, as_of_version: &str, ) -> MetadataResult<DescribeMetadataResult>

Catalog the metadata types this org supports.

Returns one DescribeMetadataObject per type, with the directory name, file suffix, and child-type relationships. This is the canonical source for package.xml <types><name> values and for the zip directory layout — handlers building deploy zips should reference this rather than hard-coding the list.

as_of_version is the API version of the catalog (e.g. "66.0"). Pass the version your tooling targets so newly-added types in newer versions don’t surface unexpectedly.

Source

pub async fn describe_value_type( &self, qualified_type_name: &str, ) -> MetadataResult<DescribeValueTypeResult>

Describe the schema of one specific metadata type.

qualified_type_name is the SOAP-namespace-qualified type name. For the standard Metadata API namespace, that’s "{http://soap.sforce.com/2006/04/metadata}ApexClass" (or any other type). The Tooling API uses "{urn:metadata.tooling.soap.sforce.com}<Type>".

Returns field-level metadata — types, requirement flags, foreign-key relationships, picklist options. Useful for validating component XML before deploy or for generating typed bindings.

Source§

impl MetadataClient

Source

pub fn builder() -> MetadataClientBuilder

Returns a builder for constructing a MetadataClient.

Source

pub fn api_version(&self) -> &str

Returns the configured Metadata API version (e.g. "66.0").

Source

pub fn http_client(&self) -> &Client

Returns a reference to the underlying reqwest client. Useful for callers who want to compose additional requests against the same connection pool.

Source

pub fn auth(&self) -> &SharedAuth

Returns the auth session backing this client.

Source

pub fn retry_policy(&self) -> &RetryPolicy

Returns the configured retry policy.

Source

pub fn endpoint_url(&self) -> String

Returns the fully-resolved SOAP endpoint URL for this client, e.g. https://my-org.my.salesforce.com/services/Soap/m/66.0.

The instance URL is read from the configured AuthSession on every call, so it reflects the current session — relevant for flows that can change instance URL on refresh (e.g. some token exchange scenarios).

Source

pub fn request_builder(&self) -> RequestBuilder

Returns a pre-configured reqwest::RequestBuilder for the SOAP endpoint, with Content-Type and SOAPAction already set.

The bearer token is not injected — the Metadata API expects it inside the envelope’s <SessionHeader>, not on the Authorization header. Fetch it via client.auth().access_token().await? and splice it into your envelope.

Security note: because the token travels in the request body, redacting the Authorization header is not enough — any middleware or proxy that logs request bodies will capture the session token in plaintext. This applies to every request this client sends, including the typed call path.

Use this only when you need to bypass the typed SoapOperation path entirely (e.g. to record raw traffic).

Source

pub async fn call<O: SoapOperation>( &self, op: &O, ) -> MetadataResult<O::Response>

Dispatch a typed SOAP operation.

This is the entry point handlers use; it builds the envelope, POSTs, retries transient failures per the configured RetryPolicy, refreshes the auth token on INVALID_SESSION_ID faults, and deserializes the response into O::Response. Returns MetadataError::Soap for server-side faults and MetadataError::Http / MetadataError::Http4xx5xx for transport-level failures.

The session token travels inside the SOAP envelope (the request body) — see the security note on request_builder before wiring body-logging middleware around this client.

Trait Implementations§

Source§

impl Clone for MetadataClient

Source§

fn clone(&self) -> MetadataClient

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for MetadataClient

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more