mirror of
https://github.com/aljazceru/pubky-core.git
synced 2026-01-09 09:14:22 +01:00
feat(pubky): use builder pattern for client::list()
This commit is contained in:
@@ -20,7 +20,7 @@ pub type EntriesTable = Database<Str, Bytes>;
|
||||
|
||||
pub const ENTRIES_TABLE: &str = "entries";
|
||||
|
||||
const MAX_LIST_LIMIT: i32 = 100;
|
||||
const MAX_LIST_LIMIT: u16 = 100;
|
||||
|
||||
impl DB {
|
||||
pub fn put_entry(
|
||||
@@ -90,7 +90,7 @@ impl DB {
|
||||
public_key: &PublicKey,
|
||||
prefix: &str,
|
||||
reverse: bool,
|
||||
limit: Option<i32>,
|
||||
limit: Option<u16>,
|
||||
cursor: Option<String>,
|
||||
) -> anyhow::Result<Vec<String>> {
|
||||
let db = self.tables.entries;
|
||||
|
||||
@@ -88,7 +88,7 @@ pub async fn get(
|
||||
public_key,
|
||||
path.as_str(),
|
||||
params.contains_key("reverse"),
|
||||
params.get("limit").and_then(|l| l.parse::<i32>().ok()),
|
||||
params.get("limit").and_then(|l| l.parse::<u16>().ok()),
|
||||
params.get("cursor").map(|cursor| cursor.into()),
|
||||
)?;
|
||||
|
||||
|
||||
@@ -28,6 +28,9 @@ pub enum Error {
|
||||
#[error("Recovery file encrypted secret key should be 32 bytes, got {0}")]
|
||||
RecoverFileInvalidSecretKeyLength(usize),
|
||||
|
||||
#[error("Could not convert the passed type into a Url")]
|
||||
InvalidUrl,
|
||||
|
||||
// === Transparent ===
|
||||
#[error(transparent)]
|
||||
Dns(#[from] SimpleDnsError),
|
||||
|
||||
@@ -12,7 +12,10 @@ use url::Url;
|
||||
|
||||
use crate::{
|
||||
error::Result,
|
||||
shared::recovery_file::{create_recovery_file, decrypt_recovery_file},
|
||||
shared::{
|
||||
list_builder::ListBuilder,
|
||||
recovery_file::{create_recovery_file, decrypt_recovery_file},
|
||||
},
|
||||
PubkyClient,
|
||||
};
|
||||
|
||||
@@ -104,6 +107,10 @@ impl PubkyClient {
|
||||
self.inner_delete(url).await
|
||||
}
|
||||
|
||||
pub fn list<T: TryInto<Url>>(&self, url: T) -> Result<ListBuilder> {
|
||||
self.inner_list(url)
|
||||
}
|
||||
|
||||
// === Helpers ===
|
||||
|
||||
/// Create a recovery file of the `keypair`, containing the secret key encrypted
|
||||
|
||||
73
pubky/src/shared/list_builder.rs
Normal file
73
pubky/src/shared/list_builder.rs
Normal file
@@ -0,0 +1,73 @@
|
||||
use reqwest::{Method, Response, StatusCode};
|
||||
use url::Url;
|
||||
|
||||
use crate::{error::Result, PubkyClient};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ListBuilder<'a> {
|
||||
url: Url,
|
||||
reverse: bool,
|
||||
limit: Option<u16>,
|
||||
cursor: Option<&'a str>,
|
||||
client: &'a PubkyClient,
|
||||
}
|
||||
|
||||
impl<'a> ListBuilder<'a> {
|
||||
pub fn new(client: &'a PubkyClient, url: Url) -> Self {
|
||||
Self {
|
||||
client,
|
||||
url,
|
||||
limit: None,
|
||||
cursor: None,
|
||||
reverse: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reverse(mut self, reverse: bool) -> Self {
|
||||
self.reverse = reverse;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn limit(mut self, limit: u16) -> Self {
|
||||
self.limit = limit.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub fn cursor(mut self, cursor: &'a str) -> Self {
|
||||
self.cursor = cursor.into();
|
||||
self
|
||||
}
|
||||
|
||||
pub async fn send(self) -> Result<Vec<String>> {
|
||||
let mut url = self.client.pubky_to_http(self.url).await?;
|
||||
|
||||
let mut query = url.query_pairs_mut();
|
||||
query.append_key_only("list");
|
||||
|
||||
if self.reverse {
|
||||
query.append_key_only("reverse");
|
||||
}
|
||||
|
||||
if let Some(limit) = self.limit {
|
||||
query.append_pair("limit", &limit.to_string());
|
||||
}
|
||||
|
||||
if let Some(cursor) = self.cursor {
|
||||
query.append_pair("cursor", cursor);
|
||||
}
|
||||
|
||||
drop(query);
|
||||
|
||||
let response = self.client.request(Method::GET, url).send().await?;
|
||||
|
||||
response.error_for_status_ref()?;
|
||||
|
||||
// TODO: bail on too large files.
|
||||
let bytes = response.bytes().await?;
|
||||
|
||||
Ok(String::from_utf8_lossy(&bytes)
|
||||
.lines()
|
||||
.map(String::from)
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
pub mod auth;
|
||||
pub mod list_builder;
|
||||
pub mod pkarr;
|
||||
pub mod public;
|
||||
pub mod recovery_file;
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::{
|
||||
PubkyClient,
|
||||
};
|
||||
|
||||
use super::pkarr::Endpoint;
|
||||
use super::{list_builder::ListBuilder, pkarr::Endpoint};
|
||||
|
||||
impl PubkyClient {
|
||||
pub async fn inner_put<T: TryInto<Url>>(&self, url: T, content: &[u8]) -> Result<()> {
|
||||
@@ -53,49 +53,15 @@ impl PubkyClient {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn list<T: TryInto<Url>>(
|
||||
&self,
|
||||
url: T,
|
||||
reverse: bool,
|
||||
limit: Option<i32>,
|
||||
cursor: Option<&str>,
|
||||
) -> Result<Vec<String>> {
|
||||
let mut url = self.pubky_to_http(url).await?;
|
||||
|
||||
let mut query = url.query_pairs_mut();
|
||||
query.append_key_only("list");
|
||||
|
||||
if reverse {
|
||||
query.append_key_only("reverse");
|
||||
}
|
||||
|
||||
if let Some(limit) = limit {
|
||||
query.append_pair("limit", &limit.to_string());
|
||||
}
|
||||
|
||||
if let Some(cursor) = cursor {
|
||||
query.append_pair("cursor", cursor);
|
||||
}
|
||||
|
||||
drop(query);
|
||||
|
||||
let response = self.request(Method::GET, url).send().await?;
|
||||
|
||||
response.error_for_status_ref()?;
|
||||
|
||||
// TODO: bail on too large files.
|
||||
let bytes = response.bytes().await?;
|
||||
|
||||
Ok(String::from_utf8_lossy(&bytes)
|
||||
.lines()
|
||||
.map(String::from)
|
||||
.collect())
|
||||
pub fn inner_list<T: TryInto<Url>>(&self, url: T) -> Result<ListBuilder> {
|
||||
Ok(ListBuilder::new(
|
||||
self,
|
||||
url.try_into().map_err(|_| Error::InvalidUrl)?,
|
||||
))
|
||||
}
|
||||
|
||||
async fn pubky_to_http<T: TryInto<Url>>(&self, url: T) -> Result<Url> {
|
||||
let mut original_url: Url = url
|
||||
.try_into()
|
||||
.map_err(|e| Error::Generic("Invalid Url".to_string()))?;
|
||||
pub(crate) async fn pubky_to_http<T: TryInto<Url>>(&self, url: T) -> Result<Url> {
|
||||
let mut original_url: Url = url.try_into().map_err(|_| Error::InvalidUrl)?;
|
||||
|
||||
if original_url.scheme() != "pubky" {
|
||||
return Ok(original_url);
|
||||
@@ -272,7 +238,7 @@ mod tests {
|
||||
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client.list(url.as_str(), false, None, None).await.unwrap();
|
||||
let list = client.list(url.as_str()).unwrap().send().await.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
list,
|
||||
@@ -289,7 +255,10 @@ mod tests {
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client
|
||||
.list(url.as_str(), false, Some(2), None)
|
||||
.list(url.as_str())
|
||||
.unwrap()
|
||||
.limit(2)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -306,7 +275,11 @@ mod tests {
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client
|
||||
.list(url.as_str(), false, Some(2), Some("a.txt"))
|
||||
.list(url.as_str())
|
||||
.unwrap()
|
||||
.limit(2)
|
||||
.cursor("a.txt")
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -323,15 +296,14 @@ mod tests {
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client
|
||||
.list(
|
||||
url.as_str(),
|
||||
false,
|
||||
Some(2),
|
||||
Some(&format!(
|
||||
"pubky://{}/pub/example.com/a.txt",
|
||||
keypair.public_key()
|
||||
)),
|
||||
)
|
||||
.list(url.as_str())
|
||||
.unwrap()
|
||||
.limit(2)
|
||||
.cursor(&format!(
|
||||
"pubky://{}/pub/example.com/a.txt",
|
||||
keypair.public_key()
|
||||
))
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -347,7 +319,13 @@ mod tests {
|
||||
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client.list(url.as_str(), true, None, None).await.unwrap();
|
||||
let list = client
|
||||
.list(url.as_str())
|
||||
.unwrap()
|
||||
.reverse(true)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
list,
|
||||
@@ -364,7 +342,11 @@ mod tests {
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client
|
||||
.list(url.as_str(), true, Some(2), None)
|
||||
.list(url.as_str())
|
||||
.unwrap()
|
||||
.reverse(true)
|
||||
.limit(2)
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
@@ -381,7 +363,12 @@ mod tests {
|
||||
{
|
||||
let url = format!("pubky://{}/pub/example.com/", keypair.public_key());
|
||||
let list = client
|
||||
.list(url.as_str(), true, Some(2), Some("d.txt"))
|
||||
.list(url.as_str())
|
||||
.unwrap()
|
||||
.reverse(true)
|
||||
.limit(2)
|
||||
.cursor("d.txt")
|
||||
.send()
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user