From 20a195bea2b7cfa891a1def0573c4f3c50911992 Mon Sep 17 00:00:00 2001 From: John Lewis Date: Thu, 4 Apr 2024 17:25:54 +0200 Subject: [PATCH] docs(bl): added more docs to `bl` crate --- crates/bl/src/fetch.rs | 13 +++++++++++++ crates/bl/src/lib.rs | 29 ++++++++++++++++++++++++++++- crates/bl/src/model_ext.rs | 17 +++++++++++++---- crates/bl/src/qr_code.rs | 3 +++ crates/bl/src/rmp_sfn.rs | 2 ++ crates/bl/src/upload/mod.rs | 8 ++++++++ 6 files changed, 67 insertions(+), 5 deletions(-) diff --git a/crates/bl/src/fetch.rs b/crates/bl/src/fetch.rs index c19e87b..7ef50a2 100644 --- a/crates/bl/src/fetch.rs +++ b/crates/bl/src/fetch.rs @@ -1,6 +1,13 @@ +//! Fetcher logic. +//! +//! This module is used mostly for first-party fetchers. If you need to fetch +//! something from the database, it should go here. + use core_types::{PhotoGroup, PhotoThumbnailDisplayParams}; use leptos::{server, server_fn::codec::Json, ServerFnError}; +/// Fetches all the [`PhotoGroup`]s owned by a +/// [`User`](core_types::UserRecordId). #[server( input = Json, output = Json, @@ -35,6 +42,8 @@ pub async fn fetch_user_owned_photo_groups( .map_err(|e: Report| crate::handle_error(e, "fetch user owned photo groups")) } +/// Fetches a [`PhotoGroup`] given its +/// [`PhotoGroupRecordId`](core_types::PhotoGroupRecordId). #[server( input = Json, output = Json, @@ -61,6 +70,8 @@ pub async fn fetch_photo_group( .map_err(|e: Report| crate::handle_error(e, "fetch photo group")) } +/// Fetches a [`PublicUser`](core_types::PublicUser) given its +/// [`UserRecordId`](core_types::UserRecordId). #[server( input = Json, output = Json, @@ -86,6 +97,8 @@ pub async fn fetch_user( .map_err(|e: Report| crate::handle_error(e, "fetch user")) } +/// Fetches a photo thumbnail ([`PhotoThumbnailDisplayParams`]) given its +/// [`PhotoRecordId`](core_types::PhotoRecordId). #[server( input = Json, output = Json, diff --git a/crates/bl/src/lib.rs b/crates/bl/src/lib.rs index 29ff0ce..9e24de6 100644 --- a/crates/bl/src/lib.rs +++ b/crates/bl/src/lib.rs @@ -1,3 +1,25 @@ +#![warn(missing_docs)] + +//! The `bl` crate is for business logic. Any arbitrary code that needs to run +//! on the server should be in the `bl` crate. Modules are based on semantic +//! divisions between functionality. +//! +//! ## Server Functions +//! Most of the logic here exists in the form of a server function. For this +//! reason, like other crates in picturepro, this crate has `hydrate` and `ssr` +//! features. If you add a dependency, 90% it should only exist under the `ssr` +//! feature. Only if you really need to pass a type through the API boundary +//! (over HTTP), or the crate is mostly/all macros (like [`thiserror`]), should +//! you add your dependency under the `hydrate` feature as well. +//! +//! ## Errors +//! This crate provides a [`handle_error`] method that consumes an +//! [`eyre::Report`](color_eyre::eyre::Report), properly handles it, and returns +//! a [`ServerFnError`]. It's best used by enclosing the main logic in an async +//! block (in which you use the `?` sugar), immediately awaiting the async +//! block, and then using `.map_err(|e| crate::handle_error(e, "generate +//! qr-code"))`. + pub mod fetch; #[cfg(feature = "ssr")] pub mod model_ext; @@ -8,11 +30,16 @@ pub mod upload; #[cfg(feature = "ssr")] use leptos::ServerFnError; +/// Consumes a [`eyre::Report`](color_eyre::eyre::Report), properly handles it, +/// and returns a [`ServerFnError`]. +/// +/// The `failed_action` parameter only used for identifying the error context in +/// logs, and it's interpolated as `"Failed to {failed_action}: {error:?}"`. #[cfg(feature = "ssr")] pub fn handle_error( error: color_eyre::eyre::Report, failed_action: &'static str, ) -> ServerFnError { - tracing::error!("Failed to {}: {:?}", failed_action, &error); + tracing::error!("Failed to {failed_action}: {error:?}"); ServerFnError::new(error) } diff --git a/crates/bl/src/model_ext.rs b/crates/bl/src/model_ext.rs index baccda6..4c4ddf4 100644 --- a/crates/bl/src/model_ext.rs +++ b/crates/bl/src/model_ext.rs @@ -1,10 +1,16 @@ +//! Provides [`ModelExt`], an extension of the [`CoreModel`] trait. + use clients::surreal::SurrealRootClient; use color_eyre::eyre::{OptionExt, Result}; use core_types::{CoreId, CoreModel}; -pub trait ModelExt: core_types::CoreModel { +/// Provides [`fetch`](ModelExt::fetch), [`create`](ModelExt::create), and +/// [`patch`](ModelExt::patch) methods for interfacing with Surreal for a given +/// model. +pub trait ModelExt: CoreModel { + /// Fetches the model from Surreal given its [`CoreModel::Id`]. fn fetch( - id: ::Id, + id: ::Id, client: &SurrealRootClient, ) -> impl std::future::Future>> + Send { async move { @@ -13,6 +19,7 @@ pub trait ModelExt: core_types::CoreModel { } } + /// Pushes a model instance to Surreal, and returns the pushed version. fn create( &self, client: &SurrealRootClient, @@ -31,8 +38,10 @@ pub trait ModelExt: core_types::CoreModel { } } + /// Patches a model in Surreal using its [`CoreModel::Id`] and a + /// [`PatchOp`](surrealdb::opt::PatchOp). fn patch( - id: ::Id, + id: ::Id, client: &SurrealRootClient, patch: surrealdb::opt::PatchOp, ) -> impl std::future::Future> + Send { @@ -43,4 +52,4 @@ pub trait ModelExt: core_types::CoreModel { } } -impl ModelExt for T {} +impl ModelExt for T {} diff --git a/crates/bl/src/qr_code.rs b/crates/bl/src/qr_code.rs index 6773231..c7c801a 100644 --- a/crates/bl/src/qr_code.rs +++ b/crates/bl/src/qr_code.rs @@ -1,3 +1,5 @@ +//! QR-code logic. + use leptos::{server, server_fn::codec::Json, ServerFnError}; /// Generate a QR code from the given data. Returns base64 encoded PNG data. @@ -21,6 +23,7 @@ pub fn generate_qr_code_inner(data: &str) -> color_eyre::eyre::Result { Ok(data) } +/// Generates a QR-code from arbitrary data. #[server( input = Json, output = Json, diff --git a/crates/bl/src/rmp_sfn.rs b/crates/bl/src/rmp_sfn.rs index 584a421..c1ca891 100644 --- a/crates/bl/src/rmp_sfn.rs +++ b/crates/bl/src/rmp_sfn.rs @@ -1,3 +1,5 @@ +//! A custom implementation of using messagepack as a leptos codec. + use http::Method; use leptos::server_fn::{ codec::{Encoding, FromReq, FromRes, IntoReq, IntoRes}, diff --git a/crates/bl/src/upload/mod.rs b/crates/bl/src/upload/mod.rs index 95456bb..875f2c9 100644 --- a/crates/bl/src/upload/mod.rs +++ b/crates/bl/src/upload/mod.rs @@ -1,3 +1,5 @@ +//! Photo upload logic. + #[cfg(feature = "ssr")] mod exif_ops; #[cfg(feature = "ssr")] @@ -25,13 +27,19 @@ fn thumbnail_size(aspect_ratio: f32) -> (u32, u32) { } } +/// Structured error type for the [`upload_photo_group`] server function. #[derive(Clone, Debug, EnumString, Display)] pub enum PhotoUploadError { + /// The image could not be parsed by the [`image`] crate. InvalidImage, + /// The request is unauthenticated. Unauthenticated, + /// Something failed internally. InternalError(String), } +/// Creates and stores a [`PhotoGroup`](core_types::PhotoGroup) and its +/// [`Photo`](core_types::Photo)s built from the [`PhotoGroupUploadParams`]. #[server( input = MessagePack, custom = RmpEncoded,