use std::path::PathBuf; use async_trait::async_trait; use bytes::Bytes; use futures::Stream; use serde_json::Value; use crate::domain::entities::file::File; use crate::domain::services::path_service::StoragePath; use crate::common::errors::DomainError; // Re-export domain repository traits for backward compatibility. // The canonical definitions now live in domain/repositories/. pub use crate::domain::repositories::file_repository::{FileReadRepository, FileWriteRepository, FileRepository}; pub use crate::domain::repositories::folder_repository::FolderRepository; // ───────────────────────────────────────────────────── // FileReadPort — application-layer alias for FileReadRepository // ───────────────────────────────────────────────────── /// Secondary port for file **reading**. /// /// Encapsulates every operation that queries state without modifying it: /// get, list, content, stream, mmap, range, path resolution. #[async_trait] pub trait FileReadPort: Send + Sync + 'static { /// Gets a file by its ID. async fn get_file(&self, id: &str) -> Result; /// Lists files in a folder. async fn list_files(&self, folder_id: Option<&str>) -> Result, DomainError>; /// Gets the full content as bytes (small/medium files only). async fn get_file_content(&self, id: &str) -> Result, DomainError>; /// Gets content as a stream (ideal for large files). async fn get_file_stream( &self, id: &str, ) -> Result> + Send>, DomainError>; /// Stream of a byte range (HTTP Range Requests, video seek). async fn get_file_range_stream( &self, id: &str, start: u64, end: Option, ) -> Result> + Send>, DomainError>; /// Memory-map of a file for zero-copy access (10–100 MB). async fn get_file_mmap(&self, id: &str) -> Result; /// Gets the logical storage path of a file. async fn get_file_path(&self, id: &str) -> Result; /// Gets the parent folder ID from a path (WebDAV). async fn get_parent_folder_id(&self, path: &str) -> Result; } // ───────────────────────────────────────────────────── // FileWritePort — all write / mutate operations // ───────────────────────────────────────────────────── /// Secondary port for file **writing**. /// /// Covers: upload (buffered + streaming), move, delete, update, /// and deferred registration for the write-behind cache. #[async_trait] pub trait FileWritePort: Send + Sync + 'static { /// Saves a new file from bytes. async fn save_file( &self, name: String, folder_id: Option, content_type: String, content: Vec, ) -> Result; /// Streaming upload — writes chunks to disk without accumulating in RAM. async fn save_file_from_stream( &self, name: String, folder_id: Option, content_type: String, stream: std::pin::Pin> + Send>>, ) -> Result; /// Moves a file to another folder. async fn move_file( &self, file_id: &str, target_folder_id: Option, ) -> Result; /// Renames a file (same folder, different name). async fn rename_file( &self, file_id: &str, new_name: &str, ) -> Result; /// Deletes a file. async fn delete_file(&self, id: &str) -> Result<(), DomainError>; /// Updates the content of an existing file. async fn update_file_content(&self, file_id: &str, content: Vec) -> Result<(), DomainError>; /// Registers file metadata WITHOUT writing content to disk (write-behind). /// /// Returns `(File, PathBuf)` where `PathBuf` is the destination path for the /// deferred write that the `WriteBehindCache` will perform. async fn register_file_deferred( &self, name: String, folder_id: Option, content_type: String, size: u64, ) -> Result<(File, PathBuf), DomainError>; // ── Trash operations ── /// Moves a file to the trash async fn move_to_trash(&self, file_id: &str) -> Result<(), DomainError>; /// Restores a file from the trash to its original location async fn restore_from_trash(&self, file_id: &str, original_path: &str) -> Result<(), DomainError>; /// Permanently deletes a file (used by the trash) async fn delete_file_permanently(&self, file_id: &str) -> Result<(), DomainError>; } // ───────────────────────────────────────────────────── // Auxiliary ports (unchanged) // ───────────────────────────────────────────────────── /// Secondary port for file path resolution #[async_trait] pub trait FilePathResolutionPort: Send + Sync + 'static { /// Gets the storage path of a file async fn get_file_path(&self, id: &str) -> Result; /// Resolves a domain path to a physical path fn resolve_path(&self, storage_path: &StoragePath) -> PathBuf; } /// Secondary port for file/directory existence verification #[async_trait] pub trait StorageVerificationPort: Send + Sync + 'static { /// Checks whether a file exists at the given path async fn file_exists(&self, storage_path: &StoragePath) -> Result; /// Checks whether a directory exists at the given path async fn directory_exists(&self, storage_path: &StoragePath) -> Result; } /// Secondary port for directory management #[async_trait] pub trait DirectoryManagementPort: Send + Sync + 'static { /// Creates directories if they do not exist async fn ensure_directory(&self, storage_path: &StoragePath) -> Result<(), DomainError>; } /// Secondary port for storage usage management #[async_trait] pub trait StorageUsagePort: Send + Sync + 'static { /// Updates storage usage statistics for a user async fn update_user_storage_usage(&self, user_id: &str) -> Result; /// Updates storage usage statistics for all users async fn update_all_users_storage_usage(&self) -> Result<(), DomainError>; } /// Generic storage service interface for calendar and contact services #[async_trait] pub trait StorageUseCase: Send + Sync + 'static { /// Handle a request with the specified action and parameters async fn handle_request(&self, action: &str, params: Value) -> Result; }