forked from herocode/horus
refactor coordinator to use shared lib models and client
This commit is contained in:
@@ -2,6 +2,13 @@ use serde::{Deserialize, Serialize};
|
||||
use thiserror::Error;
|
||||
use serde_json;
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use async_trait::async_trait;
|
||||
|
||||
// Transport implementations
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub mod transports;
|
||||
|
||||
// Import types from the main supervisor crate
|
||||
|
||||
|
||||
@@ -32,19 +39,69 @@ use jsonrpsee::{
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use http::{HeaderMap, HeaderName, HeaderValue};
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use std::path::PathBuf;
|
||||
|
||||
/// Client for communicating with Hero Supervisor OpenRPC server
|
||||
/// Requires authentication secret for all operations
|
||||
/// Transport abstraction for supervisor communication
|
||||
/// Allows different transport layers (HTTP, Mycelium, etc.)
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[async_trait]
|
||||
pub trait SupervisorTransport: Send + Sync {
|
||||
/// Send a JSON-RPC request and await the response
|
||||
async fn call(
|
||||
&self,
|
||||
method: &str,
|
||||
params: serde_json::Value,
|
||||
) -> Result<serde_json::Value, ClientError>;
|
||||
}
|
||||
|
||||
/// HTTP transport implementation using jsonrpsee
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[derive(Clone)]
|
||||
pub struct SupervisorClient {
|
||||
pub struct HttpTransport {
|
||||
client: HttpClient,
|
||||
server_url: String,
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[async_trait]
|
||||
impl SupervisorTransport for HttpTransport {
|
||||
async fn call(
|
||||
&self,
|
||||
method: &str,
|
||||
params: serde_json::Value,
|
||||
) -> Result<serde_json::Value, ClientError> {
|
||||
// params is already an array from the caller
|
||||
// jsonrpsee expects params as an array, so pass it directly
|
||||
let result: serde_json::Value = if params.is_array() {
|
||||
// Use the array directly with rpc_params
|
||||
let arr = params.as_array().unwrap();
|
||||
match arr.len() {
|
||||
0 => self.client.request(method, rpc_params![]).await?,
|
||||
1 => self.client.request(method, rpc_params![&arr[0]]).await?,
|
||||
_ => {
|
||||
// For multiple params, we need to pass them as a slice
|
||||
self.client.request(method, rpc_params![arr]).await?
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Single param not in array
|
||||
self.client.request(method, rpc_params![¶ms]).await?
|
||||
};
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
|
||||
/// Client for communicating with Hero Supervisor OpenRPC server
|
||||
/// Generic over transport layer (HTTP, Mycelium, etc.)
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[derive(Clone)]
|
||||
pub struct SupervisorClient<T: SupervisorTransport = HttpTransport> {
|
||||
transport: T,
|
||||
secret: String,
|
||||
}
|
||||
|
||||
/// Legacy type alias for backward compatibility
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub type HttpSupervisorClient = SupervisorClient<HttpTransport>;
|
||||
|
||||
/// Error types for client operations
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
#[derive(Error, Debug)]
|
||||
@@ -258,8 +315,8 @@ impl SupervisorClientBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Build the SupervisorClient
|
||||
pub fn build(self) -> ClientResult<SupervisorClient> {
|
||||
/// Build the SupervisorClient with HTTP transport
|
||||
pub fn build(self) -> ClientResult<SupervisorClient<HttpTransport>> {
|
||||
let server_url = self.url
|
||||
.ok_or_else(|| ClientError::Http("URL is required".to_string()))?;
|
||||
let secret = self.secret
|
||||
@@ -280,9 +337,10 @@ impl SupervisorClientBuilder {
|
||||
.build(&server_url)
|
||||
.map_err(|e| ClientError::Http(e.to_string()))?;
|
||||
|
||||
let transport = HttpTransport { client };
|
||||
|
||||
Ok(SupervisorClient {
|
||||
client,
|
||||
server_url,
|
||||
transport,
|
||||
secret,
|
||||
})
|
||||
}
|
||||
@@ -296,25 +354,24 @@ impl Default for SupervisorClientBuilder {
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl SupervisorClient {
|
||||
/// Create a builder for SupervisorClient
|
||||
impl SupervisorClient<HttpTransport> {
|
||||
/// Create a builder for HTTP-based SupervisorClient
|
||||
pub fn builder() -> SupervisorClientBuilder {
|
||||
SupervisorClientBuilder::new()
|
||||
}
|
||||
|
||||
/// Get the server URL
|
||||
pub fn server_url(&self) -> &str {
|
||||
&self.server_url
|
||||
}
|
||||
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
impl<T: SupervisorTransport> SupervisorClient<T> {
|
||||
/// Create a new client with a custom transport
|
||||
pub fn new(transport: T, secret: String) -> Self {
|
||||
Self { transport, secret }
|
||||
}
|
||||
|
||||
/// Test connection using OpenRPC discovery method
|
||||
/// This calls the standard `rpc.discover` method that should be available on any OpenRPC server
|
||||
pub async fn discover(&self) -> ClientResult<serde_json::Value> {
|
||||
let result: serde_json::Value = self
|
||||
.client
|
||||
.request("rpc.discover", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
self.transport.call("rpc.discover", serde_json::json!([])).await
|
||||
}
|
||||
|
||||
/// Register a new runner to the supervisor
|
||||
@@ -324,11 +381,8 @@ impl SupervisorClient {
|
||||
&self,
|
||||
name: &str,
|
||||
) -> ClientResult<()> {
|
||||
let _: () = self
|
||||
.client
|
||||
.request("runner.create", rpc_params![name])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(())
|
||||
let result = self.transport.call("runner.create", serde_json::json!([name])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Create a new job without queuing it to a runner
|
||||
@@ -337,20 +391,14 @@ impl SupervisorClient {
|
||||
&self,
|
||||
job: Job,
|
||||
) -> ClientResult<String> {
|
||||
let job_id: String = self
|
||||
.client
|
||||
.request("job.create", rpc_params![job])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(job_id)
|
||||
let result = self.transport.call("job.create", serde_json::json!([job])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// List all jobs
|
||||
pub async fn job_list(&self) -> ClientResult<Vec<Job>> {
|
||||
let jobs: Vec<Job> = self
|
||||
.client
|
||||
.request("job.list", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(jobs)
|
||||
let result = self.transport.call("job.list", serde_json::json!([])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Run a job on the appropriate runner and wait for the result (blocking)
|
||||
@@ -369,11 +417,8 @@ impl SupervisorClient {
|
||||
params["timeout"] = serde_json::json!(t);
|
||||
}
|
||||
|
||||
let result: JobRunResponse = self
|
||||
.client
|
||||
.request("job.run", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
let result = self.transport.call("job.run", serde_json::json!([params])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Start a job without waiting for the result (non-blocking)
|
||||
@@ -387,58 +432,40 @@ impl SupervisorClient {
|
||||
"job": job
|
||||
});
|
||||
|
||||
let result: JobStartResponse = self
|
||||
.client
|
||||
.request("job.start", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
let result = self.transport.call("job.start", serde_json::json!([params])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get the current status of a job
|
||||
pub async fn job_status(&self, job_id: &str) -> ClientResult<JobStatus> {
|
||||
let status: JobStatus = self
|
||||
.client
|
||||
.request("job.status", rpc_params![job_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(status)
|
||||
let result = self.transport.call("job.status", serde_json::json!([job_id])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get the result of a completed job (blocks until result is available)
|
||||
pub async fn job_result(&self, job_id: &str) -> ClientResult<JobResult> {
|
||||
let result: JobResult = self
|
||||
.client
|
||||
.request("job.result", rpc_params![job_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
let result = self.transport.call("job.result", serde_json::json!([job_id])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Remove a runner from the supervisor
|
||||
/// Authentication via Authorization header (set during client creation)
|
||||
pub async fn runner_remove(&self, runner_id: &str) -> ClientResult<()> {
|
||||
let _: () = self
|
||||
.client
|
||||
.request("runner.remove", rpc_params![runner_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(())
|
||||
let result = self.transport.call("runner.remove", serde_json::json!([runner_id])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// List all runner IDs
|
||||
pub async fn runner_list(&self) -> ClientResult<Vec<String>> {
|
||||
let runners: Vec<String> = self
|
||||
.client
|
||||
.request("runner.list", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(runners)
|
||||
let result = self.transport.call("runner.list", serde_json::json!([])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Start a specific runner
|
||||
/// Authentication via Authorization header (set during client creation)
|
||||
pub async fn start_runner(&self, actor_id: &str) -> ClientResult<()> {
|
||||
let _: () = self
|
||||
.client
|
||||
.request("runner.start", rpc_params![actor_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(())
|
||||
let result = self.transport.call("runner.start", serde_json::json!([actor_id])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Add a runner to the supervisor
|
||||
@@ -447,21 +474,21 @@ impl SupervisorClient {
|
||||
let params = serde_json::json!({
|
||||
"config": config
|
||||
});
|
||||
let _: () = self
|
||||
.client
|
||||
.request("runner.add", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
let result = self
|
||||
.transport
|
||||
.call("runner.add", serde_json::json!([params]))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get status of a specific runner
|
||||
/// Authentication via Authorization header (set during client creation)
|
||||
pub async fn get_runner_status(&self, actor_id: &str) -> ClientResult<RunnerStatus> {
|
||||
let status: RunnerStatus = self
|
||||
.client
|
||||
.request("runner.status", rpc_params![actor_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(status)
|
||||
let result = self
|
||||
.transport
|
||||
.call("runner.status", serde_json::json!([actor_id]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get logs for a specific runner
|
||||
@@ -471,11 +498,11 @@ impl SupervisorClient {
|
||||
lines: Option<usize>,
|
||||
follow: bool,
|
||||
) -> ClientResult<Vec<LogInfo>> {
|
||||
let logs: Vec<LogInfo> = self
|
||||
.client
|
||||
.request("get_runner_logs", rpc_params![actor_id, lines, follow])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(logs)
|
||||
let result = self
|
||||
.transport
|
||||
.call("get_runner_logs", serde_json::json!([actor_id, lines, follow]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Queue a job to a specific runner
|
||||
@@ -485,10 +512,10 @@ impl SupervisorClient {
|
||||
"job": job
|
||||
});
|
||||
|
||||
let _: () = self
|
||||
.client
|
||||
.request("queue_job_to_runner", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
let result = self
|
||||
.transport
|
||||
.call("queue_job_to_runner", serde_json::json!([params]))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -500,11 +527,11 @@ impl SupervisorClient {
|
||||
"timeout_secs": timeout_secs
|
||||
});
|
||||
|
||||
let result: Option<String> = self
|
||||
.client
|
||||
.request("queue_and_wait", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
let result = self
|
||||
.transport
|
||||
.call("queue_and_wait", serde_json::json!([params]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Run a job on a specific runner
|
||||
@@ -513,56 +540,56 @@ impl SupervisorClient {
|
||||
"job": job
|
||||
});
|
||||
|
||||
let result: JobResult = self
|
||||
.client
|
||||
.request("job.run", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
let result = self
|
||||
.transport
|
||||
.call("job.run", serde_json::json!([params]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get job result by job ID
|
||||
pub async fn get_job_result(&self, job_id: &str) -> ClientResult<Option<String>> {
|
||||
let result: Option<String> = self
|
||||
.client
|
||||
.request("get_job_result", rpc_params![job_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(result)
|
||||
let result = self
|
||||
.transport
|
||||
.call("get_job_result", serde_json::json!([job_id]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get status of all runners
|
||||
pub async fn get_all_runner_status(&self) -> ClientResult<Vec<(String, RunnerStatus)>> {
|
||||
let statuses: Vec<(String, RunnerStatus)> = self
|
||||
.client
|
||||
.request("get_all_runner_status", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(statuses)
|
||||
let result = self
|
||||
.transport
|
||||
.call("get_all_runner_status", serde_json::json!([]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Start all runners
|
||||
pub async fn start_all(&self) -> ClientResult<Vec<(String, bool)>> {
|
||||
let results: Vec<(String, bool)> = self
|
||||
.client
|
||||
.request("start_all", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(results)
|
||||
let result = self
|
||||
.transport
|
||||
.call("start_all", serde_json::json!([]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Stop all runners
|
||||
pub async fn stop_all(&self, force: bool) -> ClientResult<Vec<(String, bool)>> {
|
||||
let results: Vec<(String, bool)> = self
|
||||
.client
|
||||
.request("stop_all", rpc_params![force])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(results)
|
||||
let result = self
|
||||
.transport
|
||||
.call("stop_all", serde_json::json!([force]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get status of all runners (alternative method)
|
||||
pub async fn get_all_status(&self) -> ClientResult<Vec<(String, RunnerStatus)>> {
|
||||
let statuses: Vec<(String, RunnerStatus)> = self
|
||||
.client
|
||||
.request("get_all_status", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(statuses)
|
||||
let result = self
|
||||
.transport
|
||||
.call("get_all_status", serde_json::json!([]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Add a secret to the supervisor
|
||||
@@ -576,10 +603,10 @@ impl SupervisorClient {
|
||||
"secret_value": secret_value
|
||||
});
|
||||
|
||||
let _: () = self
|
||||
.client
|
||||
.request("add_secret", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
let result = self
|
||||
.transport
|
||||
.call("add_secret", serde_json::json!([params]))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -594,10 +621,10 @@ impl SupervisorClient {
|
||||
"secret_value": secret_value
|
||||
});
|
||||
|
||||
let _: () = self
|
||||
.client
|
||||
.request("remove_secret", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
let result = self
|
||||
.transport
|
||||
.call("remove_secret", serde_json::json!([params]))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -605,91 +632,87 @@ impl SupervisorClient {
|
||||
pub async fn list_secrets(&self) -> ClientResult<SupervisorInfo> {
|
||||
let params = serde_json::json!({});
|
||||
|
||||
let info: SupervisorInfo = self
|
||||
.client
|
||||
.request("list_secrets", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(info)
|
||||
let result = self
|
||||
.transport
|
||||
.call("list_secrets", serde_json::json!([params]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Stop a running job
|
||||
pub async fn job_stop(&self, job_id: &str) -> ClientResult<()> {
|
||||
let _: () = self.client
|
||||
.request("job.stop", rpc_params![job_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(())
|
||||
let result = self.transport.call("job.stop", serde_json::json!([job_id])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Delete a job from the system
|
||||
pub async fn job_delete(&self, job_id: &str) -> ClientResult<()> {
|
||||
let _: () = self.client
|
||||
.request("job.delete", rpc_params![job_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(())
|
||||
let result = self.transport.call("job.delete", serde_json::json!([job_id])).await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get supervisor information including secret counts
|
||||
pub async fn get_supervisor_info(&self) -> ClientResult<SupervisorInfo> {
|
||||
let info: SupervisorInfo = self
|
||||
.client
|
||||
.request("supervisor.info", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(info)
|
||||
let result = self
|
||||
.transport
|
||||
.call("supervisor.info", serde_json::json!([]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Get a job by ID
|
||||
pub async fn job_get(&self, job_id: &str) -> ClientResult<Job> {
|
||||
let job: Job = self
|
||||
.client
|
||||
.request("job.get", rpc_params![job_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(job)
|
||||
let result = self
|
||||
.transport
|
||||
.call("job.get", serde_json::json!([job_id]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
// ========== Auth/API Key Methods ==========
|
||||
|
||||
/// Verify the current API key
|
||||
pub async fn auth_verify(&self) -> ClientResult<AuthVerifyResponse> {
|
||||
let response: AuthVerifyResponse = self
|
||||
.client
|
||||
.request("auth.verify", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(response)
|
||||
let result = self
|
||||
.transport
|
||||
.call("auth.verify", serde_json::json!([]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Create a new API key (admin only)
|
||||
pub async fn key_create(&self, key: ApiKey) -> ClientResult<()> {
|
||||
let _: () = self
|
||||
.client
|
||||
.request("key.create", rpc_params![key])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
let result = self
|
||||
.transport
|
||||
.call("key.create", serde_json::json!([key]))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate a new API key with auto-generated key value (admin only)
|
||||
pub async fn key_generate(&self, params: GenerateApiKeyParams) -> ClientResult<ApiKey> {
|
||||
let api_key: ApiKey = self
|
||||
.client
|
||||
.request("key.generate", rpc_params![params])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(api_key)
|
||||
let result = self
|
||||
.transport
|
||||
.call("key.generate", serde_json::json!([params]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
|
||||
/// Remove an API key (admin only)
|
||||
pub async fn key_delete(&self, key_id: String) -> ClientResult<()> {
|
||||
let _: () = self
|
||||
.client
|
||||
.request("key.delete", rpc_params![key_id])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
let result = self
|
||||
.transport
|
||||
.call("key.delete", serde_json::json!([key_id]))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// List all API keys (admin only)
|
||||
pub async fn key_list(&self) -> ClientResult<Vec<ApiKey>> {
|
||||
let keys: Vec<ApiKey> = self
|
||||
.client
|
||||
.request("key.list", rpc_params![])
|
||||
.await.map_err(|e| ClientError::JsonRpc(e))?;
|
||||
Ok(keys)
|
||||
let result = self
|
||||
.transport
|
||||
.call("key.list", serde_json::json!([]))
|
||||
.await?;
|
||||
serde_json::from_value(result).map_err(ClientError::Serialization)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user