diff --git a/.gitignore b/.gitignore index 96ef6c0..0a36603 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,6 @@ /target Cargo.lock +*# +.#* +*~ + diff --git a/server/nm-store/src/store.rs b/server/nm-store/src/store.rs index 521a4ab..2a01d44 100644 --- a/server/nm-store/src/store.rs +++ b/server/nm-store/src/store.rs @@ -65,32 +65,89 @@ pub struct NoteStore(Arc); type NoteResult = core::result::Result; -impl NoteStore { - /// Initializes a new instance of the note store. Note that the - /// note store holds an Arc internally; this code is (I think) - /// safe to Send. - pub async fn new(url: &str) -> NoteResult { - let pool = SqlitePool::connect(url).await?; - Ok(NoteStore(Arc::new(pool))) - } +// After wrestling for a while with the fact that 'box' is a reserved +// word in Rust, I decided to just go with Zettle (note) and Kasten +// (box). +impl NoteStore { + /// Initializes a new instance of the note store. Note that the + /// note store holds an Arc internally; this code is (I think) + /// safe to Send. + pub async fn new(url: &str) -> NoteResult { + let pool = SqlitePool::connect(url).await?; + Ok(NoteStore(Arc::new(pool))) + } /// Erase all the data in the database and restore it - /// to its original empty form. Do not use unless you - /// really, really want that to happen. - pub async fn reset_database(&self) -> NoteResult<()> { - reset_database(&*self.0).await.map_err(NoteStoreError::DBError) - } + /// to its original empty form. Do not use unless you + /// really, really want that to happen. + pub async fn reset_database(&self) -> NoteResult<()> { + reset_database(&*self.0) + .await + .map_err(NoteStoreError::DBError) + } - /// Fetch page by slug - /// - /// Supports the use case of the user navigating to a known place - /// via a bookmark or other URL. Since the title isn't clear from - /// the slug, the slug is insufficient to generate a new page, so - /// this use case says that in the event of a failure to find the - /// requested page, return a basic NotFound. - pub async fn get_kasten_by_slug(&self, slug: &str) -> NoteResult> { - let page = select_kasten_by_slug(&*self.0, slug).await?; - Ok(page) - } + /// Fetch page by slug + /// + /// Supports the use case of the user navigating to a known place + /// via a bookmark or other URL. Since the title isn't clear from + /// the slug, the slug is insufficient to generate a new page, so + /// this use case says that in the event of a failure to find the + /// requested page, return a basic NotFound. + pub async fn get_kasten_by_slug(&self, slug: &str) -> NoteResult> { + Ok(select_kasten_by_slug(&*self.0, slug).await?) + } + + pub async fn get_kasten_by_title(&self, title: &str) -> NoteResult> { + let kasten = select_page_by_title(&mut tx, title).await?; + if kasten.len() > 0 { + return kasten + } + + let mut tx = self.0.begin().await?; + let new slug = generate_slug(&mut tx, title).await?; + let new zettlekasten = create_unique_zettlekasten(&title, &slug); + let _ = insert_zettle(&zettlekasten).await?; + tx.commit().await?; + + Ok(vec![zettlekasten]) + } + + pub async fn insert_zettle( + &self, + note: &NewNote, + parent_note_id: &str, + location: i64 + ) -> NoteResult { + let note = { + let mut new_note = note.clone(); + new_note.id = friendly_id::create(); + new_note + }; + + let references = build_references(¬e.content); + + let mut tx = self.0.begin().await?; + let location = cmp::min( + assert_max_child_position_for_note(&mut tx, parent_note_id).await? + 1, + location); + + insert_one_new_note(&mut tx, ¬e).await?; + make_room_for_new_note(&mut tx, parent_id, location).await?; + insert_note_to_note_relationship(&mut tx, parent_id, note.id, location, "note"); + + let found_references = find_all_page_references_for(&mut tx, &references).await?; + let mut known_reference_ids: Vec = Vec::new(); + for one_reference in new_references.iter() { + let new slug = generate_slug(&mut tx, one_reference).await?; + let new zettlekasten = create_unique_zettlekasten(&one_reference, &slug); + let _ = insert_zettle(&zettlekasten).await?; + known_reference_ids.push(slug); + } + + known_reference_ids.append(&mut found_references.iter().map(|r| PageId(r.id)).collect()); + let _ = insert_note_to_page_relationships(&mut tx, new_note_id, &known_reference_ids).await?; + tx.commit().await?; + Ok(note.id); + } }