use crate::{
Endpoint,
http::{ApiClient, errors::ApiError},
types::{FileContent, FileInfo},
};
pub struct FileResource {
pub path: String,
pub app_id: String,
pub(crate) client: ApiClient,
}
impl FileResource {
pub fn new(api: ApiClient, path: &str, app_id: &str) -> Self {
Self {
client: api,
app_id: app_id.to_string(),
path: path.to_string(),
}
}
pub async fn write(&self, content: &str) -> Result<bool, ApiError> {
let endpoint =
Endpoint::put_app_file(&self.app_id, &self.path, content);
self.client
.request_endpoint::<bool>(endpoint)
.await?
.into_bool_result()
}
pub async fn read(&self, path: &str) -> Result<FileContent, ApiError> {
self.client
.request_endpoint(Endpoint::read_app_file(&self.app_id, path))
.await?
.into_result_t()
}
pub async fn delete(&self) -> Result<bool, ApiError> {
let endpoint = Endpoint::delete_app_file(&self.app_id, &self.path);
self.client
.request_endpoint::<bool>(endpoint)
.await?
.into_bool_result()
}
pub async fn move_to(
&self,
destination_path: &str,
) -> Result<bool, ApiError> {
let endpoint = Endpoint::move_app_file(
&self.app_id,
&self.path,
destination_path,
);
self.client
.request_endpoint::<bool>(endpoint)
.await?
.into_bool_result()
}
pub fn find_by_path<'a>(
files: &'a [FileResource],
path: &'a str,
) -> Option<&'a FileResource> {
files.iter().find(|file| file.path == path)
}
pub async fn all_files(
&self,
path: &str,
) -> Result<Vec<FileInfo>, ApiError> {
let endpoint = Endpoint::list_app_files(&self.app_id, path);
self.client
.request_endpoint(endpoint)
.await?
.into_result_t()
}
}
#[cfg(test)]
mod tests {
use super::FileResource;
use crate::http::ApiClient;
fn make_file(path: &str) -> FileResource {
unsafe { std::env::set_var("API_TOKEN", "test") };
FileResource {
path: path.to_string(),
app_id: "app-123".to_string(),
client: ApiClient::new(),
}
}
#[test]
fn find_by_path_returns_match() {
let files =
vec![make_file("/app/main.py"), make_file("/app/config.json")];
let found = FileResource::find_by_path(&files, "/app/main.py");
assert!(found.is_some());
assert_eq!(found.unwrap().path, "/app/main.py");
}
#[test]
fn find_by_path_returns_none_when_missing() {
let files = vec![make_file("/app/main.py")];
assert!(FileResource::find_by_path(&files, "/app/other.py").is_none());
}
}