about summary refs log tree commit diff stats
path: root/crates/rocie-server/src/storage/sql/get/recipe
diff options
context:
space:
mode:
Diffstat (limited to 'crates/rocie-server/src/storage/sql/get/recipe')
-rw-r--r--crates/rocie-server/src/storage/sql/get/recipe/mod.rs90
1 files changed, 74 insertions, 16 deletions
diff --git a/crates/rocie-server/src/storage/sql/get/recipe/mod.rs b/crates/rocie-server/src/storage/sql/get/recipe/mod.rs
index 9d6dc79..f433541 100644
--- a/crates/rocie-server/src/storage/sql/get/recipe/mod.rs
+++ b/crates/rocie-server/src/storage/sql/get/recipe/mod.rs
@@ -1,15 +1,38 @@
 use crate::{
     app::App,
-    storage::sql::recipe::{Recipe, RecipeId},
+    storage::sql::{
+        recipe::{CooklangRecipe, Recipe, RecipeId},
+        recipe_parent::RecipeParentId,
+    },
 };
 
 use sqlx::query;
 
+pub(crate) mod parse {
+    use crate::storage::sql::recipe::conversion;
+
+    #[derive(thiserror::Error, Debug)]
+    pub(crate) enum Error {
+        #[error("Failed to convert from cooklang recipe to our own struct")]
+        Conversion(#[from] conversion::Error),
+    }
+}
+
+async fn recipe_from_content(app: &App, content: &str) -> Result<CooklangRecipe, parse::Error> {
+    // NOTE: We can ignore warnings here, as we should already have handled them at the recipe
+    // insert point. <2026-01-31>
+    let (output, _warnings) = cooklang::parse(content)
+        .into_result()
+        .expect("The values in the db should always be valid, as we checked before inserting them");
+
+    Ok(CooklangRecipe::from(app, output).await?)
+}
+
 impl Recipe {
     pub(crate) async fn from_id(app: &App, id: RecipeId) -> Result<Option<Self>, from_id::Error> {
         let record = query!(
             "
-        SELECT content, path
+        SELECT name, parent, content
         FROM recipies
         WHERE id = ?
 ",
@@ -21,11 +44,33 @@ impl Recipe {
         if let Some(record) = record {
             Ok(Some(Self {
                 id,
-                path: record
-                    .path
-                    .parse()
-                    .expect("Was a path before, should still be one"),
-                content: record.content,
+                content: recipe_from_content(app, &record.content).await?,
+                name: record.name,
+                parent: record.parent.map(|id| RecipeParentId::from_db(&id)),
+            }))
+        } else {
+            Ok(None)
+        }
+    }
+
+    pub(crate) async fn from_name(app: &App, name: String) -> Result<Option<Self>, from_id::Error> {
+        let record = query!(
+            "
+        SELECT id, parent, content
+        FROM recipies
+        WHERE name = ?
+",
+            name
+        )
+        .fetch_optional(&app.db)
+        .await?;
+
+        if let Some(record) = record {
+            Ok(Some(Self {
+                id: RecipeId::from_db(&record.id),
+                content: recipe_from_content(app, &record.content).await?,
+                name,
+                parent: record.parent.map(|id| RecipeParentId::from_db(&id)),
             }))
         } else {
             Ok(None)
@@ -35,31 +80,39 @@ impl Recipe {
     pub(crate) async fn get_all(app: &App) -> Result<Vec<Self>, get_all::Error> {
         let records = query!(
             "
-        SELECT id, content, path
+        SELECT id, name, parent, content
         FROM recipies
 ",
         )
         .fetch_all(&app.db)
         .await?;
 
-        Ok(records
-            .into_iter()
-            .map(|record| Self {
+        let mut output = vec![];
+        for record in records {
+            output.push(Self {
                 id: RecipeId::from_db(&record.id),
-                path: record.path.parse().expect("Is still valid"),
-                content: record.content,
-            })
-            .collect())
+                content: recipe_from_content(app, &record.content).await?,
+                name: record.name,
+                parent: record.parent.map(|id| RecipeParentId::from_db(&id)),
+            });
+        }
+
+        Ok(output)
     }
 }
 
 pub(crate) mod from_id {
     use actix_web::ResponseError;
 
+    use crate::storage::sql::get::recipe::parse;
+
     #[derive(thiserror::Error, Debug)]
     pub(crate) enum Error {
-        #[error("Failed to execute the sql query")]
+        #[error("Failed to execute the sql query: `{0}`")]
         SqlError(#[from] sqlx::Error),
+
+        #[error("Failed to parse the recipe content as cooklang recipe: `{0}`")]
+        RecipeParse(#[from] parse::Error),
     }
 
     impl ResponseError for Error {}
@@ -68,10 +121,15 @@ pub(crate) mod from_id {
 pub(crate) mod get_all {
     use actix_web::ResponseError;
 
+    use crate::storage::sql::get::recipe::parse;
+
     #[derive(thiserror::Error, Debug)]
     pub(crate) enum Error {
         #[error("Failed to execute the sql query")]
         SqlError(#[from] sqlx::Error),
+
+        #[error("Failed to parse the recipe content as cooklang recipe")]
+        RecipeParse(#[from] parse::Error),
     }
 
     impl ResponseError for Error {}