pub mod auth;
pub mod issue;
pub mod oauth;
pub mod pull;
pub mod repo;
pub mod secrets;
pub mod service_auth;
pub mod session;
pub mod types;
use std::sync::OnceLock;
use serde::de::DeserializeOwned;
use tangled_api::xrpc::{self, XrpcError};
pub const DEFAULT_API_BASE: &str = "https://api.tangled.org";
pub const DEFAULT_KNOT_HOST: &str = "knot1.tangled.sh";
pub const DEFAULT_KNOT: &str = "https://knot1.tangled.sh";
pub(crate) fn http() -> &'static reqwest::Client {
static HTTP: OnceLock<reqwest::Client> = OnceLock::new();
HTTP.get_or_init(|| {
reqwest::Client::builder()
.user_agent(concat!("tangled-cli/", env!("CARGO_PKG_VERSION")))
.build()
.expect("static HTTP client configuration must be valid")
})
}
pub(crate) async fn xrpc_send<T>(
rb: reqwest::RequestBuilder,
) -> Result<T, XrpcError>
where
T: DeserializeOwned,
{
crate::progress::with_spinner("Contacting server...", xrpc::send(rb)).await
}
pub(crate) async fn xrpc_send_unit(
rb: reqwest::RequestBuilder,
) -> Result<(), XrpcError> {
crate::progress::with_spinner("Contacting server...", xrpc::send_unit(rb))
.await
}
#[allow(dead_code)]
pub(crate) async fn xrpc_send_bytes(
rb: reqwest::RequestBuilder,
) -> Result<Vec<u8>, XrpcError> {
crate::progress::with_spinner("Contacting server...", xrpc::send_bytes(rb))
.await
}
pub(crate) fn uri_rkey(uri: &str) -> Option<String> {
uri.rsplit('/').next().map(|s| s.to_string())
}
pub(crate) fn uri_did(uri: &str) -> Option<String> {
let parts: Vec<&str> = uri.split('/').collect();
if parts.len() >= 3 {
Some(parts[2].to_string())
} else {
None
}
}
pub(crate) fn now_rfc3339() -> String {
chrono::Utc::now().to_rfc3339()
}