pub struct Client { /* private fields */ }Expand description
A HEY client: one authenticated identity, presenting mail from All Accounts unless
derived for one linked account with Client::for_account.
Clients are cheap to clone and share their connection pool, credentials and cache.
Implementations§
Source§impl Client
impl Client
Sourcepub async fn for_account(&self, account_id: i64) -> Result<Client, Error>
pub async fn for_account(&self, account_id: i64) -> Result<Client, Error>
Derives a client that presents mail from one linked account and acts as that account’s user and default sender. The account is checked against the identity first, so a stale or foreign id fails here rather than on the first read. That check goes out through an unscoped client derived from this one: the identity belongs to the whole login, and reading it filtered to an account would leave nothing to check the account against.
Calendar, journal, habits and time tracking belong to the identity, so they read the same through a scoped client.
Sourcepub async fn default_sender_id(&self) -> Result<i64, Error>
pub async fn default_sender_id(&self) -> Result<i64, Error>
The sender a message goes out as when the caller names none: the scoped account’s default sender, or the identity’s default sender for All Accounts.
Sourcepub async fn account_user_id(&self) -> Result<i64, Error>
pub async fn account_user_id(&self) -> Result<i64, Error>
The identity’s user in the scoped account, which is what a record is filed under.
Source§impl Client
impl Client
Sourcepub fn builder(config: Config) -> ClientBuilder
pub fn builder(config: Config) -> ClientBuilder
A ClientBuilder for config, at the defaults.
Sourcepub fn new(
config: Config,
provider: impl TokenProvider + 'static,
) -> Result<Client, Error>
Available on crate feature reqwest only.
pub fn new( config: Config, provider: impl TokenProvider + 'static, ) -> Result<Client, Error>
reqwest only.A client with the default settings and a bearer token, on the HTTP client the SDK
ships. Without the reqwest feature there is no such client, and a
ClientBuilder with an HttpClient of the application’s own is the way in.
Sourcepub fn account_id(&self) -> Option<i64>
pub fn account_id(&self) -> Option<i64>
The linked account this client presents, or None for All Accounts.
Sourcepub fn operation(
&self,
route: &'static Route,
params: &[&dyn Display],
) -> Operation
pub fn operation( &self, route: &'static Route, params: &[&dyn Display], ) -> Operation
Starts a request for one of the modelled routes. Generated service methods call this; reach for it directly only to add headers or query parameters they do not expose.
Sourcepub fn request(&self, method: Method, path: impl Into<String>) -> Operation
pub fn request(&self, method: Method, path: impl Into<String>) -> Operation
Starts a request for a path the model does not cover. The path is relative to the
base URL and gets the same credentials, .json suffix, account scope and retry
treatment as a modelled one.
Sourcepub async fn send<T: DeserializeOwned>(
&self,
operation: Operation,
) -> Result<T, Error>
pub async fn send<T: DeserializeOwned>( &self, operation: Operation, ) -> Result<T, Error>
Sends an operation and decodes its JSON body.
Sourcepub async fn send_unit(&self, operation: Operation) -> Result<(), Error>
pub async fn send_unit(&self, operation: Operation) -> Result<(), Error>
Sends an operation whose answer carries no body worth reading.
Sourcepub async fn send_text(&self, operation: Operation) -> Result<String, Error>
pub async fn send_text(&self, operation: Operation) -> Result<String, Error>
Sends an operation and reads its body as text: the HTML page a route serves no JSON for.
Sourcepub async fn send_optional<T: DeserializeOwned>(
&self,
operation: Operation,
) -> Result<Option<T>, Error>
pub async fn send_optional<T: DeserializeOwned>( &self, operation: Operation, ) -> Result<Option<T>, Error>
Sends an operation that answers a status meaning “nothing there” with None.
Sourcepub async fn send_page<T: DeserializeOwned>(
&self,
operation: Operation,
) -> Result<Page<T>, Error>
pub async fn send_page<T: DeserializeOwned>( &self, operation: Operation, ) -> Result<Page<T>, Error>
Sends a paginated read and keeps the cursor HEY answered with.
Sourcepub async fn next_page<T: DeserializeOwned>(
&self,
page: &Page<T>,
) -> Result<Option<Page<T>>, Error>
pub async fn next_page<T: DeserializeOwned>( &self, page: &Page<T>, ) -> Result<Option<Page<T>>, Error>
Reads the page after the given one, or None when HEY named no next page. A
Link header pointing off the HEY origin is refused rather than followed. The read
announces itself as the operation the first page came from, so a whole walk shows
up as one thing rather than as a list read followed by anonymous requests, and it
is resent under that operation’s retry policy.
Sourcepub async fn each_page<T: DeserializeOwned>(
&self,
first: Page<T>,
visit: impl FnMut(&Page<T>) -> bool,
) -> Result<(), Error>
pub async fn each_page<T: DeserializeOwned>( &self, first: Page<T>, visit: impl FnMut(&Page<T>) -> bool, ) -> Result<(), Error>
Reads every page after the first, calling visit with each one. Stops early when
visit answers false. A walk that reaches the client’s page limit with pages
still to read stops there and says so, as Error::pagination_capped: the pages
visited stand, and the caller knows they were not all of them.
Sourcepub async fn execute(&self, operation: Operation) -> Result<Response, Error>
pub async fn execute(&self, operation: Operation) -> Result<Response, Error>
Sends an operation: asks the hooks whether it may run, applies credentials and account scope, retries transient failures when the operation is idempotent, resends once after a refreshed 401, and answers a cached body on 304. Non-2xx statuses become errors unless the operation treats them as empty.
Source§impl Client
impl Client
Sourcepub fn form(&self, method: Method, path: &str) -> Result<Operation, Error>
pub fn form(&self, method: Method, path: &str) -> Result<Operation, Error>
A request to one of the endpoints HEY serves only as a browser form: the path as the
caller wrote it, a browser’s Accept, and the redirect taken for the answer rather
than followed.
It is not retried, whatever its method — a form post that may already have gone through is not one to repeat on a timeout or a 503. A 401 is the exception the whole client makes: credentials are refreshed and the request goes out once more, since a request HEY refused for want of a token never reached the write it would repeat.
The model describes none of these paths, so say what the call means with
Operation::info before sending it, or the hooks will only hear that something raw
went out. crate::services::write_info builds that.
A path that already is a URL is checked before it is taken: HTTPS goes anywhere, plain HTTP only back to the base URL’s own host. That check is what this can fail on.
Sourcepub async fn send_form(
&self,
operation: Operation,
) -> Result<FormResponse, Error>
pub async fn send_form( &self, operation: Operation, ) -> Result<FormResponse, Error>
Sends a form request and reads the redirect it answered with.
A failure keeps the code, hint and request id HEY answered with. Go flattens every status but 401 into a bare “Form request failed (HTTP 503)”, which loses the request id support would look the call up by and tells a caller nothing it could act on; a 503 here still reads as the retryable API error it is.
Source§impl Client
impl Client
pub fn attachments(&self) -> Attachments<'_>
pub fn boxes(&self) -> Boxes<'_>
pub fn bulk_replies(&self) -> BulkReplies<'_>
pub fn calendar_events(&self) -> CalendarEvents<'_>
pub fn calendar_periods(&self) -> CalendarPeriods<'_>
pub fn calendar_todos(&self) -> CalendarTodos<'_>
pub fn calendars(&self) -> Calendars<'_>
pub fn clearances(&self) -> Clearances<'_>
pub fn clips(&self) -> Clips<'_>
pub fn collections(&self) -> Collections<'_>
pub fn contacts(&self) -> Contacts<'_>
pub fn designations(&self) -> Designations<'_>
pub fn entries(&self) -> Entries<'_>
pub fn extenzions(&self) -> Extenzions<'_>
pub fn folders(&self) -> Folders<'_>
pub fn habits(&self) -> Habits<'_>
pub fn identity(&self) -> Identity<'_>
pub fn journal(&self) -> Journal<'_>
pub fn messages(&self) -> Messages<'_>
pub fn postings(&self) -> Postings<'_>
pub fn publications(&self) -> Publications<'_>
pub fn search(&self) -> Search<'_>
pub fn snippets(&self) -> Snippets<'_>
pub fn stickies(&self) -> Stickies<'_>
pub fn time_tracks(&self) -> TimeTracks<'_>
pub fn topics(&self) -> Topics<'_>
pub fn workflows(&self) -> Workflows<'_>
Source§impl Client
impl Client
Sourcepub async fn get_all(&self, path: &str) -> Result<Vec<Value>, Error>
pub async fn get_all(&self, path: &str) -> Result<Vec<Value>, Error>
Reads a paginated path to its end and hands back the items of every page as one
list. Each page has to decode as a JSON array. Use this for the paths the model
does not cover; a modelled read walks with Client::each_page, which keeps the
records typed. A walk that reaches the client’s page limit with pages still to
read is an error, Error::pagination_capped, rather than a shorter list that
looks complete.
Sourcepub async fn get_all_with_limit(
&self,
path: &str,
limit: usize,
) -> Result<Vec<Value>, Error>
pub async fn get_all_with_limit( &self, path: &str, limit: usize, ) -> Result<Vec<Value>, Error>
Reads a paginated path until limit items are in hand, or to its end when limit
is zero. The last page is trimmed to land on exactly limit.
Sourcepub async fn follow_pagination(
&self,
first: &Response,
first_page_count: usize,
limit: usize,
) -> Result<Vec<Value>, Error>
pub async fn follow_pagination( &self, first: &Response, first_page_count: usize, limit: usize, ) -> Result<Vec<Value>, Error>
Reads the pages after one already in hand, and hands back their items. Say how many
the first page held as first_page_count, so a limit counts the whole walk;
limit of zero reads to the end.
A Response names no route, so the pages are read on the client’s own retry
settings, as Client::get_all reads them. A modelled read walks on with
Client::next_page or Client::each_page, which keep its policy.
Source§impl Client
impl Client
Sourcepub async fn get(&self, path: &str) -> Result<Response, Error>
pub async fn get(&self, path: &str) -> Result<Response, Error>
Reads a path the model does not cover.
Sourcepub async fn get_html(&self, path: &str) -> Result<Response, Error>
pub async fn get_html(&self, path: &str) -> Result<Response, Error>
Reads the HTML representation, for the pages HEY serves no JSON for.
Sourcepub async fn get_csv(&self, path: &str) -> Result<Response, Error>
pub async fn get_csv(&self, path: &str) -> Result<Response, Error>
Reads an export, which HEY streams as a file rather than a document.
Sourcepub fn csv(&self, path: &str) -> Result<Operation, Error>
pub fn csv(&self, path: &str) -> Result<Operation, Error>
A request for one of the exports HEY streams as a file. This and Client::get_csv
stand to each other as Client::form does to Client::post_form: a call that
has something to say about itself builds the operation here and gives it an
Operation::info before sending it.
Sourcepub async fn get_blob(&self, path: &str) -> Result<Response, Error>
pub async fn get_blob(&self, path: &str) -> Result<Response, Error>
Reads a file whole. Client::download_blob writes one out as it arrives instead,
for a file too large to want in memory.
Sourcepub async fn download_blob(
&self,
path: &str,
destination: &mut (impl AsyncWrite + Unpin),
) -> Result<(u64, HeaderMap), Error>
pub async fn download_blob( &self, path: &str, destination: &mut (impl AsyncWrite + Unpin), ) -> Result<(u64, HeaderMap), Error>
Writes a file to destination as it arrives, and answers how many bytes went and
what headers came with them. Nothing is read into memory, and nothing is resent:
once bytes are on their way to the destination a second attempt would double them.
Sourcepub async fn post(
&self,
path: &str,
body: &impl Serialize,
) -> Result<Response, Error>
pub async fn post( &self, path: &str, body: &impl Serialize, ) -> Result<Response, Error>
Posts a JSON body to a path the model does not cover.
Sourcepub async fn post_mutation(
&self,
path: &str,
body: &impl Serialize,
) -> Result<Response, Error>
pub async fn post_mutation( &self, path: &str, body: &impl Serialize, ) -> Result<Response, Error>
Posts to an endpoint that may answer with something other than JSON.
Sourcepub async fn put(
&self,
path: &str,
body: &impl Serialize,
) -> Result<Response, Error>
pub async fn put( &self, path: &str, body: &impl Serialize, ) -> Result<Response, Error>
Puts a JSON body to a path the model does not cover.
Sourcepub async fn patch(
&self,
path: &str,
body: &impl Serialize,
) -> Result<Response, Error>
pub async fn patch( &self, path: &str, body: &impl Serialize, ) -> Result<Response, Error>
Patches a path the model does not cover with a JSON body.
Sourcepub async fn patch_mutation(
&self,
path: &str,
body: &impl Serialize,
) -> Result<Response, Error>
pub async fn patch_mutation( &self, path: &str, body: &impl Serialize, ) -> Result<Response, Error>
Patches an endpoint that may answer with something other than JSON.
Sourcepub async fn delete(&self, path: &str) -> Result<Response, Error>
pub async fn delete(&self, path: &str) -> Result<Response, Error>
Deletes at a path the model does not cover.
Sourcepub async fn post_form(
&self,
path: &str,
fields: &[(&str, &str)],
) -> Result<FormResponse, Error>
pub async fn post_form( &self, path: &str, fields: &[(&str, &str)], ) -> Result<FormResponse, Error>
Posts a form the way a browser would, and captures the redirect HEY answers with
rather than following it. FormResponse::extract_id reads the created record’s
id out of that redirect.
This and the three below are Client::form and Client::send_form together. A
call that has something to say about itself builds the operation with those two
instead, and gives it an Operation::info on the way.
Sourcepub async fn patch_form(
&self,
path: &str,
fields: &[(&str, &str)],
) -> Result<FormResponse, Error>
pub async fn patch_form( &self, path: &str, fields: &[(&str, &str)], ) -> Result<FormResponse, Error>
Patches through the form endpoint, the way a browser’s edit form would.
Sourcepub async fn delete_form(&self, path: &str) -> Result<FormResponse, Error>
pub async fn delete_form(&self, path: &str) -> Result<FormResponse, Error>
Deletes through the form endpoint, which answers a redirect. The request carries no body, and so no content type either.
Sourcepub async fn post_multipart(
&self,
path: &str,
content_type: String,
body: Bytes,
) -> Result<FormResponse, Error>
pub async fn post_multipart( &self, path: &str, content_type: String, body: Bytes, ) -> Result<FormResponse, Error>
Posts a multipart body the caller assembled, for the endpoints that take a file.