use serde_json::Value;
use super::Collection;
use crate::client::Client;
use crate::client::transport::{Request, encode_segment};
use crate::error::Result;
use crate::model::{Cal, CollectionName, Entry, Mbg, Sgv, Timestamp};
use crate::query::Filter;
#[derive(Debug, Clone)]
pub struct Entries {
client: Client,
}
impl Entries {
pub(crate) const fn new(client: Client) -> Self {
Self { client }
}
#[must_use]
pub fn sgv(&self) -> Collection<Sgv> {
Collection::new(self.client.clone(), Filter::new().eq("type", "sgv"))
}
#[must_use]
pub fn mbg(&self) -> Collection<Mbg> {
Collection::new(self.client.clone(), Filter::new().eq("type", "mbg"))
}
#[must_use]
pub fn cal(&self) -> Collection<Cal> {
Collection::new(self.client.clone(), Filter::new().eq("type", "cal"))
}
#[must_use]
pub fn all(&self) -> Collection<Entry> {
Collection::new(self.client.clone(), Filter::new())
}
pub async fn current(&self) -> Result<Option<Entry>> {
let resp = self
.client
.inner
.execute(Request::get(
"api/v1/entries/current.json",
"api/v1/entries/current",
))
.await?;
let entries: Vec<Entry> = resp.json()?;
Ok(entries.into_iter().next())
}
pub async fn times(&self, prefix: &str, pattern: &str, count: usize) -> Result<Vec<Entry>> {
let path = format!(
"api/v1/times/{}/{}.json",
encode_segment(prefix),
encode_segment(pattern)
);
let resp = self
.client
.inner
.execute(
Request::get(path, "api/v1/times/{prefix}/{regex}")
.query("count", count.to_string()),
)
.await?;
Ok(super::collection::decode_docs(resp.json()?))
}
pub async fn slice(
&self,
storage: CollectionName,
field: &str,
entry_type: &str,
prefix: &str,
pattern: &str,
count: usize,
) -> Result<Vec<Value>> {
let path = format!(
"api/v1/slice/{}/{}/{}/{}/{}.json",
storage.name(),
encode_segment(field),
encode_segment(entry_type),
encode_segment(prefix),
encode_segment(pattern)
);
self.client
.inner
.execute(
Request::get(
path,
"api/v1/slice/{storage}/{field}/{type}/{prefix}/{regex}",
)
.query("count", count.to_string()),
)
.await?
.json()
}
pub async fn count(&self, filter: &Filter) -> Result<u64> {
let mut filter = filter.clone();
if !filter.mentions("date") && !filter.mentions("dateString") {
filter = filter.gte("date", Timestamp::EPOCH);
}
let rows: Vec<Value> = self
.client
.inner
.execute(
Request::get("api/v1/count/entries/where", "api/v1/count/{storage}/where")
.queries(filter.v1_pairs()),
)
.await?
.json()?;
Ok(rows
.iter()
.filter_map(|row| row.get("count").and_then(Value::as_u64))
.sum())
}
pub async fn echo(&self, storage: CollectionName, filter: &Filter) -> Result<Value> {
self.client
.inner
.execute(
Request::get(
format!("api/v1/echo/{}", storage.name()),
"api/v1/echo/{storage}",
)
.queries(filter.v1_pairs()),
)
.await?
.json()
}
}