Skip to content

Commit

Permalink
feat: collate strings with frontmatter query
Browse files Browse the repository at this point in the history
  • Loading branch information
Teajey committed Jun 4, 2024
1 parent de728ab commit 566ae58
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 36 deletions.
38 changes: 2 additions & 36 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,44 +5,10 @@ mod markup;
mod route;

use anyhow::{anyhow, Result};
use axum::{
extract::{Path, State},
http::StatusCode,
routing, Json, Router,
};
use axum::{routing, Router};
use camino::Utf8PathBuf;
use notify::{RecursiveMode, Watcher};

async fn frontmatter_collate_strings_get(
State(markdown_files): State<frontmatter_file::keeper::ArcMutex>,
Path(key): Path<String>,
) -> Result<Json<Vec<String>>, StatusCode> {
let keeper = markdown_files.lock().map_err(|err| {
eprintln!("Failed to lock data on a get_collate_strings request: {err}");
StatusCode::INTERNAL_SERVER_ERROR
})?;
let mut values = keeper
.files()
.filter_map(|fmf| fmf.frontmatter())
.filter_map(|fm| fm.get(&key))
.filter_map(|v| match v {
serde_yaml::Value::String(v) => Some(vec![v.clone()]),
serde_yaml::Value::Sequence(seq) => seq
.iter()
.map(|v| match v {
serde_yaml::Value::String(v) => Some(v.clone()),
_ => None,
})
.collect(),
_ => None,
})
.flatten()
.collect::<Vec<_>>();
values.sort();
values.dedup();
Ok(Json(values))
}

async fn run() -> Result<()> {
let mut args = std::env::args();
let port = args
Expand Down Expand Up @@ -74,7 +40,7 @@ async fn run() -> Result<()> {
)
.route(
"/frontmatter/collate_strings/:key",
routing::get(frontmatter_collate_strings_get),
routing::post(route::collate_strings::post).get(route::collate_strings::get),
)
.with_state(markdown_files);

Expand Down
78 changes: 78 additions & 0 deletions src/route/collate_strings.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
use std::collections::HashMap;
use std::str::FromStr;

use axum::{
extract::{Path, Query, State},
http::StatusCode,
Json,
};

use super::{lock_keeper, query_files};

use crate::{
frontmatter_file::{self, FrontmatterFile},
frontmatter_query::FrontmatterQuery,
};

fn collate_strings_from_files<'a>(
files: impl Iterator<Item = &'a FrontmatterFile>,
key: &str,
) -> Vec<String> {
files
.filter_map(|fmf| fmf.frontmatter())
.filter_map(|fm| fm.get(key))
.filter_map(|v| match v {
serde_yaml::Value::String(v) => Some(vec![v.clone()]),
serde_yaml::Value::Sequence(seq) => seq
.iter()
.map(|v| match v {
serde_yaml::Value::String(v) => Some(v.clone()),
_ => None,
})
.collect(),
_ => None,
})
.flatten()
.collect()
}

pub async fn get(
State(markdown_files): State<frontmatter_file::keeper::ArcMutex>,
Path(key): Path<String>,
) -> Result<Json<Vec<String>>, StatusCode> {
let keeper = lock_keeper(&markdown_files)?;
let files = keeper.files();

let mut values = collate_strings_from_files(files, &key);

values.sort();
values.dedup();

Ok(Json(values))
}

pub async fn post(
State(markdown_files): State<frontmatter_file::keeper::ArcMutex>,
params: Query<HashMap<String, String>>,
Path(key): Path<String>,
Json(query): Json<FrontmatterQuery>,
) -> Result<Json<Vec<String>>, StatusCode> {
let keeper = lock_keeper(&markdown_files)?;
let files = keeper.files();

let intersect = params
.get("intersect")
.map(|p| bool::from_str(p))
.transpose()
.map_err(|_| StatusCode::BAD_REQUEST)?
.unwrap_or_default();

let files = query_files(files, &query, None, intersect);

let mut values = collate_strings_from_files(files, &key);

values.sort();
values.dedup();

Ok(Json(values))
}
1 change: 1 addition & 0 deletions src/route/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod collate_strings;
pub mod frontmatter_file;
pub mod frontmatter_list;

Expand Down

0 comments on commit 566ae58

Please sign in to comment.