diff --git a/Cargo.lock b/Cargo.lock index acccca7..4983f08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -73,8 +73,9 @@ dependencies = [ "leptos_meta", "leptos_router", "serde", + "sqlx", "thiserror", - "toml 0.8.8", + "toml 0.8.9", ] [[package]] @@ -665,9 +666,9 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "eyre" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6267a1fa6f59179ea4afc8e50fd8612a3cc60bc858f786ff877a4a8cb042799" +checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" dependencies = [ "indenter", "once_cell", @@ -693,7 +694,7 @@ dependencies = [ "serde", "slug", "thiserror", - "toml 0.8.8", + "toml 0.8.9", "tracing", "tree-sitter", "tree-sitter-c", @@ -2418,10 +2419,13 @@ version = "0.1.0" dependencies = [ "app", "axum", + "femark", "leptos", "leptos_axum", + "serde", "sqlx", "tokio", + "toml 0.8.9", "tower", "tower-http", ] @@ -2997,9 +3001,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325" dependencies = [ "serde", "serde_spanned", @@ -3018,9 +3022,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap 2.2.1", "serde", @@ -3182,9 +3186,9 @@ dependencies = [ [[package]] name = "tree-sitter-javascript" -version = "0.20.1" +version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edbc663376bdd294bd1f0a6daf859aedb9aa5bdb72217d7ad8ba2d5314102cf7" +checksum = "c042e378617c3c55a42953ce3c7c7d37fd9633c4f89f72553841f42384be3949" dependencies = [ "cc", "tree-sitter", @@ -3242,9 +3246,9 @@ dependencies = [ [[package]] name = "tree-sitter-typescript" -version = "0.20.3" +version = "0.20.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a75049f0aafabb2aac205d7bb24da162b53dcd0cfb326785f25a2f32efa8071a" +checksum = "0ff97e56624fa2868c719f431c3121e5f56f401a5a409c17b5b56c1558b7eefe" dependencies = [ "cc", "tree-sitter", diff --git a/app/Cargo.toml b/app/Cargo.toml index 3930d8c..3eb7e83 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -11,9 +11,13 @@ leptos_axum = { workspace = true, optional = true } http.workspace = true thiserror.workspace = true -serde = { version = "1"} +serde = { version = "1" } femark = { version = "0.1.5", optional = true } toml = { version = "0.8.8", optional = true } +sqlx = { version = "0.7", features = [ + "runtime-tokio-rustls", + "sqlite", +], optional = true } [features] default = [] @@ -25,6 +29,7 @@ ssr = [ "dep:leptos_axum", "dep:femark", "dep:toml", + "dep:sqlx", ] [package.metadata.cargo-all-features] diff --git a/app/src/components.rs b/app/src/components.rs index 229c7c7..9f43e82 100644 --- a/app/src/components.rs +++ b/app/src/components.rs @@ -1,2 +1,2 @@ pub mod ui; -pub mod slingshot; +pub mod api; diff --git a/app/src/components/api.rs b/app/src/components/api.rs new file mode 100644 index 0000000..6e64c9c --- /dev/null +++ b/app/src/components/api.rs @@ -0,0 +1,17 @@ +use leptos::*; +use crate::components::ui::articles::Article; + +#[server] +pub async fn get_blog_posts() -> Result, ServerFnError> { + use sqlx::*; + + let pool: SqlitePool = use_context::().expect("couldn't get pool context"); + + let result = + sqlx::query_as::<_, Article>("select * from blog where content_type like 'game'") + .fetch_all(&pool) + .await?; + + Ok(result) +} + diff --git a/app/src/components/slingshot.rs b/app/src/components/slingshot.rs deleted file mode 100644 index c9ccbfe..0000000 --- a/app/src/components/slingshot.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::components::ui::articles::ArticleInterface; -use leptos::*; - -#[server] -pub async fn slingshot(path: String) -> Result, ServerFnError> { - use serde::Deserialize; - - #[derive(Deserialize)] - struct ArticleFrontmatter { - content_type: String, - title: String, - date: String, - } - - let mut articles = vec![]; - - for file in std::fs::read_dir(path)? { - let fileinfo = file?; - let filepath = fileinfo.path(); - - if let Some(filetype) = filepath.extension() { - if filetype == "md" { - let file = std::fs::read_to_string(filepath)?; - let html_from_md = - femark::process_markdown_to_html_with_frontmatter(&file.to_string(), true) - .expect("Problem processing markdown"); - let content = html_from_md.content; - let _toc = html_from_md.toc; - - if let Some(front_raw) = html_from_md.frontmatter { - if let Some(front_code) = front_raw.code_block { - let toml: ArticleFrontmatter = toml::from_str(&front_code.source)?; - - // println!("{} {}", &toml.date, &toml.title); - articles.push(ArticleInterface { - content_type: toml.content_type, - title: toml.title, - date: toml.date, - content, - }) - } - } - } - } - } - - Ok(articles) -} diff --git a/app/src/components/ui/articles.rs b/app/src/components/ui/articles.rs index 85bd626..f6cd685 100644 --- a/app/src/components/ui/articles.rs +++ b/app/src/components/ui/articles.rs @@ -1,10 +1,11 @@ -use crate::components::slingshot::*; use crate::components::ui::containers::*; +use crate::components::api::*; use leptos::*; use serde::*; #[derive(Clone, Serialize, Deserialize)] -pub struct ArticleInterface { +#[cfg_attr(feature = "ssr", derive(sqlx::FromRow))] +pub struct Article { pub content_type: String, pub title: String, pub date: String, // make datetime? @@ -12,7 +13,7 @@ pub struct ArticleInterface { } #[component] -pub fn Article(data: ArticleInterface) -> impl IntoView { +pub fn Article(data: Article) -> impl IntoView { view! {
@@ -31,7 +32,8 @@ pub fn Article(data: ArticleInterface) -> impl IntoView { pub fn ArticleBuilder() -> impl IntoView { let data_resource = create_local_resource( || (), - |_| async move { slingshot("./public/blog".to_string()).await }, + |_| async move { get_blog_posts().await }, + // |_| async move { slingshot("./public/blog".to_string()).await }, ); let articles_view = move || { diff --git a/server/Cargo.toml b/server/Cargo.toml index 38b7b34..92b9445 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -13,3 +13,6 @@ tokio.workspace = true tower.workspace = true tower-http.workspace = true sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "sqlite"] } +toml = "0.8.8" +femark = "0.1.5" +serde = "1.0.196" diff --git a/server/src/db.rs b/server/src/db.rs index a5748e8..f718072 100644 --- a/server/src/db.rs +++ b/server/src/db.rs @@ -1,6 +1,87 @@ use leptos::*; -use sqlx::{Connection, SqliteConnection}; +use serde::*; +use sqlx::*; -pub async fn db() -> Result { - Ok(SqliteConnection::connect("sqlite::memory:").await?) +use app::components::ui::articles::Article; + +pub async fn db_build(pool: SqlitePool) -> Result<(), ServerFnError> { + let _ = query("CREATE TABLE blog (content_type TEXT, title TEXT, date TEXT, content TEXT)") + .execute(&pool) + .await?; + + #[derive(Deserialize)] + struct ArticleFrontmatter { + content_type: String, + title: String, + date: String, + } + + for file in std::fs::read_dir("./public/blog".to_string())? { + let fileinfo = file?; + let filepath = fileinfo.path(); + + if let Some(filetype) = filepath.extension() { + if filetype == "md" { + let file = std::fs::read_to_string(filepath)?; + let html_from_md = + femark::process_markdown_to_html_with_frontmatter(&file.to_string(), true) + .expect("Problem processing markdown"); + let content = html_from_md.content; + let _toc = html_from_md.toc; + + if let Some(front_raw) = html_from_md.frontmatter { + if let Some(front_code) = front_raw.code_block { + let toml: ArticleFrontmatter = toml::from_str(&front_code.source)?; + + let article = Article { + content_type: toml.content_type, + title: toml.title, + date: toml.date, + content, + }; + + let _ = sqlx::query( + " + INSERT INTO + blog (content_type, title, date, content) + VALUES + ($1, $2, $3, $4) + ", + ) + .bind(article.content_type) + .bind(article.title) + .bind(article.date) + .bind(article.content) + .execute(&pool) + .await?; + } + } + } + } + } + + Ok(()) +} + +pub async fn start_pool() -> Result { + println!( + " +⠄⠄⠄⠄⢀⡤⣖⣞⣮⢾⢽⣳⢯⢿⢷⣦⣄⠄⠄⠐⠄ +⠐⠄⠄⣴⣯⣯⢷⣻⣺⢽⣫⢾⣝⡵⡯⣾⣽⢷⣄⠄⠄ +⠄⢀⣼⢿⡽⣾⢯⣷⣻⣽⢽⣳⣳⢽⡺⡮⣫⢯⢿⣦⠄ +⠄⣼⣿⢽⡯⣿⡽⣾⡿⣞⣯⢷⢯⢯⢯⢯⡺⡪⡳⣻⠄ +⣴⣿⣿⣽⣟⣷⣟⣯⣿⡽⣞⣯⢿⡽⡽⡵⣝⢮⣫⣺⠄ +⠄⠄⠉⠉⠛⠛⠛⠛⠛⠻⠿⠿⠿⣿⣿⡿⣿⣽⣾⣾⡀ +⠐⡀⠢⠄⡀⠄⢀⣄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⠄⢀⠣ +⡀⠂⠈⣪⣌⡤⢾⠿⠕⢤⣤⣨⣠⢤⠡⠄⠄⡌⠄⡐⡐ +⠐⠈⠄⠱⣻⡻⠶⢦⠶⠯⠟⢟⢯⢳⢩⡂⡆⡇⡐⡐⢌ +⢁⠐⠄⠈⣾⣓⢝⣛⡛⡗⣞⣗⢕⡕⢕⠕⡸⡀⠂⠌⡂ +⡀⠂⡁⠄⡿⣕⢷⣻⢽⢝⢞⢮⢳⠑⠅⢑⢜⠜⣬⢐⢈ +⠄⢁⣀⣴⠋⠪⠳⠹⠵⠹⠘⠈⠂⠁⡐⡸⡘⣠⡳⡣⣪ +⣽⢟⣿⡣⠄⢸⡄⠠⠠⡠⢠⢐⠨⡐⣴⣹⡨⣞⣎⢎⢺ +⠏⠟⠛⠃⠄⠘⠛⠊⠊⠘⠐⠅⠇⠻⠛⠓⠛⠛⠪⠓⠹ +db goin up" + ); + + Ok(SqlitePool::connect("sqlite::memory:").await?) } diff --git a/server/src/main.rs b/server/src/main.rs index 41a4d6d..8e17c87 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -4,20 +4,29 @@ use fileserv::file_and_error_handler; use leptos::*; use leptos_axum::{generate_route_list, LeptosRoutes}; -pub mod fileserv; pub mod db; +pub mod fileserv; #[tokio::main] async fn main() { - use db::*; - let mut conn = db().await.expect("DB error"); let conf = get_configuration(None).await.unwrap(); let leptos_options = conf.leptos_options; let addr = leptos_options.site_addr; let routes = generate_route_list(App); + use db::*; + let pool = start_pool().await.expect("pool error"); + let _ = db_build(pool.clone()).await.unwrap(); + let app = Router::new() - .leptos_routes(&leptos_options, routes, App) + .leptos_routes_with_context( + &leptos_options, + routes, + move || { + provide_context(pool.clone()); + }, + App, + ) .fallback(file_and_error_handler) .with_state(leptos_options);