eternalfest_core 0.18.2

Core crate for Eternalfest
Documentation
use crate::blob::{BlobId, MediaType};
use crate::core::Instant;
use crate::user::{UserId, UserIdRef};
use async_trait::async_trait;
use auto_impl::auto_impl;
use etwin_core::types::AnyError;
use etwin_core::{declare_new_string, declare_new_uuid};
#[cfg(feature = "serde")]
use etwin_serde_tools::{Deserialize, Serialize};

declare_new_uuid! {
  pub struct DriveId(Uuid);
  pub type ParseError = DriveIdParseError;
  const SQL_NAME = "drive_id";
}

declare_new_uuid! {
  pub struct FileId(Uuid);
  pub type ParseError = FileIdParseError;
  const SQL_NAME = "file_id";
}

declare_new_uuid! {
  pub struct DirectoryId(Uuid);
  pub type ParseError = DirectoryIdParseError;
  const SQL_NAME = "directory_id";
}

declare_new_uuid! {
  pub struct DriveItemId(Uuid);
  pub type ParseError = DriveItemIdParseError;
  const SQL_NAME = "drive_item_id";
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", rename = "Directory"))]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DirectoryIdRef {
  pub id: DirectoryId,
}

declare_new_string! {
  pub struct DriveItemDisplayName(String);
  pub type ParseError = DriveItemDisplayNameParseError;
  const PATTERN = r"^\S.{0,99}$";
  const SQL_NAME = "drive_item_display_name";
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", rename = "Drive"))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Drive {
  pub id: DriveId,
  pub owner: UserIdRef,
  pub root: DirectoryIdRef,
  pub created_at: Instant,
  pub updated_at: Instant,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", rename = "File"))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct File {
  pub id: FileId,
  pub display_name: DriveItemDisplayName,
  pub byte_size: u32,
  pub media_type: MediaType,
  pub created_at: Instant,
  pub updated_at: Instant,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(tag = "type", rename = "Directory"))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Directory {
  pub id: DirectoryId,
  pub display_name: DriveItemDisplayName,
  #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
  pub children: Option<Vec<DriveItem>>,
  pub created_at: Instant,
  pub updated_at: Instant,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize), serde(untagged))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum DriveItem {
  Directory(Directory),
  File(File),
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GetDriveOptions {
  pub id: DriveId,
}

#[derive(Debug, thiserror::Error)]
pub enum GetDriveError {
  #[error("Failed to find drive: {:?}", .0)]
  NotFound(DriveId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GetDriveByOwnerOptions {
  pub id: UserId,
}

#[derive(Debug, thiserror::Error)]
pub enum GetDriveByOwnerError {
  #[error("Failed to find user drive, user not found: {:?}", .0)]
  NotFound(UserId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

impl GetDriveByOwnerError {
  pub fn other<E>(e: E) -> Self
  where
    E: ::std::error::Error + Send + Sync + 'static,
  {
    Self::Other(Box::new(e))
  }
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GetItemByPathOptions {
  pub drive: DriveId,
  pub path: Vec<DriveItemDisplayName>,
}

#[derive(Debug, thiserror::Error)]
pub enum GetItemByPathError {
  #[error("Failed to find drive, user not found: {:?}", .0)]
  NotFound(DriveId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GetDirectoryOptions {
  pub id: DirectoryId,
}

#[derive(Debug, thiserror::Error)]
pub enum GetDirectoryError {
  #[error("Failed to find directory: {:?}", .0)]
  NotFound(DirectoryId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[derive(Debug, thiserror::Error)]
pub enum GetDirectoryChildrenError {
  #[error("Failed to find directory: {:?}", .0)]
  NotFound(DirectoryId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct GetFileOptions {
  pub id: FileId,
}

#[derive(Debug, thiserror::Error)]
pub enum GetFileError {
  #[error("Failed to find file: {:?}", .0)]
  NotFound(FileId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[derive(Debug, thiserror::Error)]
pub enum GetFileDataError {
  #[error("Failed to find file: {:?}", .0)]
  NotFound(FileId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CreateFileOptions {
  pub parent_id: DirectoryId,
  pub blob_id: BlobId,
  pub display_name: DriveItemDisplayName,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CreateStoreFileOptions {
  pub parent_id: DirectoryId,
  pub blob_id: BlobId,
  pub display_name: DriveItemDisplayName,
  // If `Some`, check that the drive owner corresponds to the provided UserId.
  pub check_owner: Option<UserId>,
}

#[derive(Debug, thiserror::Error)]
pub enum CreateFileError {
  #[error("Failed to find parent directory")]
  ParentNotFound,
  #[error("Failed to create as current user is not the drive owner")]
  NotOwner,
  #[error(transparent)]
  Other(#[from] AnyError),
}

impl CreateFileError {
  pub fn other<E>(e: E) -> Self
  where
    E: ::std::error::Error + Send + Sync + 'static,
  {
    Self::Other(Box::new(e))
  }
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CreateDirectoryOptions {
  pub parent_id: DirectoryId,
  pub display_name: DriveItemDisplayName,
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CreateStoreDirectoryOptions {
  pub parent_id: DirectoryId,
  pub display_name: DriveItemDisplayName,
  // If `Some`, check that the drive owner corresponds to the provided UserId.
  pub check_owner: Option<UserId>,
}

#[derive(Debug, thiserror::Error)]
pub enum CreateDirectoryError {
  #[error("Failed to find parent directory")]
  ParentNotFound,
  #[error("Failed to create as current user is not the drive owner")]
  NotOwner,
  #[error(transparent)]
  Other(#[from] AnyError),
}

impl CreateDirectoryError {
  pub fn other<E>(e: E) -> Self
  where
    E: ::std::error::Error + Send + Sync + 'static,
  {
    Self::Other(Box::new(e))
  }
}

#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct DeleteItemOptions {
  pub id: DriveItemId,
}

#[derive(Debug, thiserror::Error)]
pub enum DeleteItemError {
  #[error("Failed to find node to delete: {:?}", .0)]
  NotFound(DriveItemId),
  #[error(transparent)]
  Other(#[from] AnyError),
}

#[async_trait]
#[auto_impl(&, Arc)]
pub trait FileStore: Send + Sync {
  async fn get_drive(&self, options: &GetDriveOptions) -> Result<Drive, GetDriveError>;
  async fn get_drive_by_owner(&self, options: &GetDriveByOwnerOptions) -> Result<Drive, GetDriveByOwnerError>;
  async fn get_item_by_path(&self, options: &GetItemByPathOptions) -> Result<DriveItem, GetItemByPathError>;
  async fn create_directory(&self, options: &CreateStoreDirectoryOptions) -> Result<Directory, CreateDirectoryError>;
  async fn get_directory(&self, options: &GetDirectoryOptions) -> Result<Directory, GetDirectoryError>;
  async fn get_directory_children(
    &self,
    options: &GetDirectoryOptions,
  ) -> Result<Vec<DriveItem>, GetDirectoryChildrenError>;
  async fn create_file(&self, options: &CreateStoreFileOptions) -> Result<File, CreateFileError>;
  async fn get_file(&self, options: &GetFileOptions) -> Result<File, GetFileError>;
  async fn get_file_data(&self, options: &GetFileOptions) -> Result<Vec<u8>, GetFileDataError>;
  async fn delete_item(&self, options: &DeleteItemOptions) -> Result<(), DeleteItemError>;
}