aboutsummaryrefslogtreecommitdiffstats
path: root/crates/daemon/src/api/client/mod.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/daemon/src/api/client/mod.rs')
-rw-r--r--crates/daemon/src/api/client/mod.rs84
1 files changed, 74 insertions, 10 deletions
diff --git a/crates/daemon/src/api/client/mod.rs b/crates/daemon/src/api/client/mod.rs
index 71fa0e37..c588fb09 100644
--- a/crates/daemon/src/api/client/mod.rs
+++ b/crates/daemon/src/api/client/mod.rs
@@ -1,4 +1,5 @@
use eyre::{Context as EyreContext, Result};
+use time::OffsetDateTime;
use tonic::Code;
use tonic::transport::{Channel, Endpoint, Uri};
use tower::service_fn;
@@ -8,8 +9,11 @@ use hyper_util::rt::TokioIo;
#[cfg(unix)]
use tokio::net::UnixStream;
+use crate::api::generated;
+use crate::api::generated::control::{ForceSyncReply, ForceSyncRequest, PathsReply, PathsRequest};
+use crate::api::generated::history::{HistoryEntry, HistoryRequest};
use crate::{
- aclient::{history::History, settings::Settings},
+ aclient::history::History,
api::{
DAEMON_PROTOCOL_VERSION, DAEMON_VERSION,
generated::{
@@ -18,18 +22,49 @@ use crate::{
},
history::{
EndHistoryReply, EndHistoryRequest, StartHistoryReply, StartHistoryRequest,
- TailHistoryReply, TailHistoryRequest,
- history_client::HistoryClient as HistoryServiceClient,
+ TailHistoryRequest, history_client::HistoryClient as HistoryServiceClient,
},
},
},
};
-fn daemon_matches_expected(version: &str, protocol: u32) -> bool {
+pub use crate::api::generated::history::{HistoryEventKind, TailHistoryReply};
+
+fn normalize_optional_field(value: &str) -> Option<String> {
+ let trimmed = value.trim();
+ if trimmed.is_empty() {
+ None
+ } else {
+ Some(trimmed.to_owned())
+ }
+}
+
+pub fn history_entry_to_history(entry: HistoryEntry) -> History {
+ let timestamp = OffsetDateTime::from_unix_timestamp_nanos(i128::from(entry.timestamp))
+ .expect("Daemon history timestamp should always be valid");
+
+ History {
+ id: entry.id.into(),
+ timestamp,
+ duration: entry.duration,
+ exit: entry.exit,
+ command: entry.command,
+ cwd: entry.cwd,
+ session: entry.session,
+ hostname: entry.hostname,
+ author: entry.author,
+ intent: normalize_optional_field(&entry.intent),
+ deleted_at: None,
+ }
+}
+
+#[must_use]
+pub fn daemon_matches_expected(version: &str, protocol: u32) -> bool {
version == DAEMON_VERSION && protocol == DAEMON_PROTOCOL_VERSION
}
-fn daemon_mismatch_message(version: &str, protocol: u32) -> String {
+#[must_use]
+pub fn daemon_mismatch_message(version: &str, protocol: u32) -> String {
if protocol == DAEMON_PROTOCOL_VERSION {
format!("daemon is out of date: expected {DAEMON_VERSION}, got {version}")
} else {
@@ -99,6 +134,11 @@ pub struct HistoryClient {
client: HistoryServiceClient<Channel>,
}
+pub struct Range {
+ pub start: OffsetDateTime,
+ pub end: OffsetDateTime,
+}
+
// Wrap the grpc client
impl HistoryClient {
#[cfg(unix)]
@@ -141,6 +181,24 @@ impl HistoryClient {
Ok(self.client.start_history(req).await?.into_inner())
}
+ pub async fn history(&mut self, session: String, range: Option<Range>) -> Result<Vec<History>> {
+ let req = HistoryRequest {
+ session,
+ range: range.map(|r| generated::history::Range {
+ start: r.start.unix_timestamp() as u64,
+ end: r.end.unix_timestamp() as u64,
+ }),
+ };
+
+ let reply = self.client.history(req).await?.into_inner();
+
+ Ok(reply
+ .entries
+ .into_iter()
+ .map(history_entry_to_history)
+ .collect())
+ }
+
pub async fn end_history(
&mut self,
id: String,
@@ -152,7 +210,7 @@ impl HistoryClient {
Ok(self.client.end_history(req).await?.into_inner())
}
- pub(crate) async fn tail_history(&mut self) -> Result<tonic::Streaming<TailHistoryReply>> {
+ pub async fn tail_history(&mut self) -> Result<tonic::Streaming<TailHistoryReply>> {
Ok(self
.client
.tail_history(TailHistoryRequest {})
@@ -196,10 +254,16 @@ impl ControlClient {
Ok(Self { client })
}
- /// Connect using settings.
- #[cfg(unix)]
- pub async fn from_settings(settings: &Settings) -> Result<Self> {
- Self::new(settings.daemon.socket_path.clone()).await
+ pub async fn paths(&mut self) -> Result<PathsReply> {
+ Ok(self.client.paths(PathsRequest {}).await?.into_inner())
+ }
+
+ pub async fn force_sync(&mut self) -> Result<ForceSyncReply> {
+ Ok(self
+ .client
+ .force_sync(ForceSyncRequest {})
+ .await?
+ .into_inner())
}
pub async fn status(&mut self) -> Result<StatusReply> {