/*
* Hanzo Cloud API
*
* The Hanzo Cloud API as a customer calls it: every operation under /v1/ except the operator's admin product, relay routes, legacy spellings and capabilities still reached by flag. Tagged by product: the first path segment after /v1/.
*
* The version of the OpenAPI document: v1
*
* Generated by: https://openapi-generator.tech
*/
use reqwest;
use serde::{Deserialize, Serialize, de::Error as _};
use crate::{apis::ResponseContent, models};
use super::{Error, configuration, ContentType};
/// struct for typed errors of method [`get_author`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetAuthorError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`get_author_basis`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum GetAuthorBasisError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`post_author_connect`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PostAuthorConnectError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`post_author_deploys_record`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PostAuthorDeploysRecordError {
UnknownValue(serde_json::Value),
}
/// struct for typed errors of method [`post_author_repos_verify`]
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(untagged)]
pub enum PostAuthorReposVerifyError {
UnknownValue(serde_json::Value),
}
/// Returns the caller's author-program dashboard: enrolment status, linked forge login, verified repositories and owner-wide claims, recorded deploys, accrued / pending / paid royalty, and the payout history. It answers ONE OF TWO SHAPES from this address. An org that has never connected gets {\"isAuthor\": false, \"defaultShareBps\", \"badgeBase\"} — an honest \"not enrolled\" rather than a 404, so the console can render the connect form. An enrolled org gets the dashboard: isAuthor, id, status, githubLogin, verified, verifyCode, verifyFile, verifySnippet, shareBps, badgeBase, repos, orgs, deploys, accruedCents, pendingCents, paidCents, payouts and ledger. For an APPROVED author this read ALSO runs the accrual sweep opportunistically, so the dashboard is self-updating. That is why the royalty AUDIT lives at its own address: an audit must not move the money it is auditing.
pub async fn get_author(configuration: &configuration::Configuration, ) -> Result<std::collections::HashMap<String, serde_json::Value>, Error<GetAuthorError>> {
let uri_str = format!("{}/v1/author", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `std::collections::HashMap<String, serde_json::Value>`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `std::collections::HashMap<String, serde_json::Value>`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<GetAuthorError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Returns the AUDIT TRAIL behind the caller's own royalty: every ledger row with the spend it was computed from, the share applied at the time, the platform's matching half, whether each row satisfies the formula, and the attribution edges that already existed when the row was written. It answers ONE OF TWO SHAPES. An org that has never connected gets {\"isAuthor\": false, \"defaultShareBps\"} — never a 404, which would answer \"is this org an author?\" for anyone who asked. An enrolled org gets the basis: isAuthor, id, status, asOf, shareBps, platformShareBps, defaultShareBps, shareSource, settlesTo, method (the formula, the rate card and the sizing), ledger, reconciliation, window, and period when one was requested. This read NEVER sweeps, and that is the point of it being a separate address from the dashboard: an audit must not move the money it is auditing, so calling it N times leaves the balances and the ledger byte-identical.
pub async fn get_author_basis(configuration: &configuration::Configuration, period: Option<&str>) -> Result<std::collections::HashMap<String, serde_json::Value>, Error<GetAuthorBasisError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_period = period;
let uri_str = format!("{}/v1/author/basis", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::GET, &uri_str);
if let Some(ref param_value) = p_period {
req_builder = req_builder.query(&[("period", ¶m_value.to_string())]);
}
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `std::collections::HashMap<String, serde_json::Value>`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `std::collections::HashMap<String, serde_json::Value>`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<GetAuthorBasisError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Enrols the caller's org in the author program at status \"connected\" and returns its enrolment, including the verify code the file method needs. It is IDEMPOTENT: a second call returns the same enrolment rather than a conflict. The forge login is taken from IAM's LINKED account for the provider when there is one — that is identity proof, not a claim — and only otherwise from the login in the body, which then has to be proven per repository. Connecting does not admit an org to earning: a platform reviewer approves that separately. Answers 201 when it enrolled the org and 200 when it found an existing enrolment.
pub async fn post_author_connect(configuration: &configuration::Configuration, connect_request: models::ConnectRequest) -> Result<models::Enrolment, Error<PostAuthorConnectError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_connect_request = connect_request;
let uri_str = format!("{}/v1/author/connect", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_connect_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Enrolment`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Enrolment`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<PostAuthorConnectError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Records that the caller's org deployed a project built from a source repository, which is the edge that makes an author's work earn royalty. It is deliberately NOT an error for a deploy to attribute to nobody: a project built from no repository, or from one no author has verified, answers {\"recorded\": false, \"reason\"} so a deploy pipeline can fire this on every deploy without branching. Attribution resolves per-repository first, then owner-wide, so a repository with its own claim always earns for its own author. A deploy of a Hanzo-maintained template attributes to the platform treasury, and a self-deploy (the author's own org deploying its own repository) is recorded for provenance but excluded from accrual. The edge is idempotent per repository+project+org. Answers 201 when it recorded a new edge and 200 otherwise.
pub async fn post_author_deploys_record(configuration: &configuration::Configuration, deploy_request: models::DeployRequest) -> Result<models::DeployRecord, Error<PostAuthorDeploysRecordError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_deploy_request = deploy_request;
let uri_str = format!("{}/v1/author/deploys/record", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_deploy_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::DeployRecord`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::DeployRecord`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<PostAuthorDeploysRecordError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}
/// Proves that the caller owns a repository — or a whole OWNER — and records the claim, which is what makes deploys of that code earn royalty. Ownership is proven the SAME two ways in both cases, tried in order: an IAM-linked forge token with admin or push permission, or a hanzo.json on the default branch carrying the author's verify code. Claiming an OWNER proves it against that owner's \".github\" control repository, and is exactly as strong as a per-repository claim — an owner the caller cannot prove is refused with 422, never assumed. A per-repository claim wins over an owner-wide one, so a specifically-claimed repository always earns for its own author. A repository another author has already verified is a 409. The org must have connected first. Answers 201 when it recorded a new claim and 200 when the claim already existed.
pub async fn post_author_repos_verify(configuration: &configuration::Configuration, verify_request: models::VerifyRequest) -> Result<models::Claim, Error<PostAuthorReposVerifyError>> {
// add a prefix to parameters to efficiently prevent name collisions
let p_verify_request = verify_request;
let uri_str = format!("{}/v1/author/repos/verify", configuration.base_path);
let mut req_builder = configuration.client.request(reqwest::Method::POST, &uri_str);
if let Some(ref user_agent) = configuration.user_agent {
req_builder = req_builder.header(reqwest::header::USER_AGENT, user_agent.clone());
}
if let Some(ref token) = configuration.bearer_access_token {
req_builder = req_builder.bearer_auth(token.to_owned());
};
req_builder = req_builder.json(&p_verify_request);
let req = req_builder.build()?;
let resp = configuration.client.execute(req).await?;
let status = resp.status();
let content_type = resp
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("application/octet-stream");
let content_type = super::ContentType::from(content_type);
if !status.is_client_error() && !status.is_server_error() {
let content = resp.text().await?;
match content_type {
ContentType::Json => serde_json::from_str(&content).map_err(Error::from),
ContentType::Text => return Err(Error::from(serde_json::Error::custom("Received `text/plain` content type response that cannot be converted to `models::Claim`"))),
ContentType::Unsupported(unknown_type) => return Err(Error::from(serde_json::Error::custom(format!("Received `{unknown_type}` content type response that cannot be converted to `models::Claim`")))),
}
} else {
let content = resp.text().await?;
let entity: Option<PostAuthorReposVerifyError> = serde_json::from_str(&content).ok();
Err(Error::ResponseError(ResponseContent { status, content, entity }))
}
}