From 32f54b51afe153546d87f86a0e260486dcb17355 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Tue, 26 Jul 2022 22:53:37 +0100 Subject: feat(GET /notes): add first implementation for notes retrieval --- README.md | 196 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..1e36c2d --- /dev/null +++ b/README.md @@ -0,0 +1,196 @@ +--- +title: joyce - record your thoughts as they come +author: Federico Igne +date: \today +--- + +`joyce` is an attempt at building a tool for rapid notetaking, i.e., quick collection of short thoughts that can come to mind at any point. + +On a high-level, this system should be: + +- *Hubiquitous*, needs to be available (read/write) whenever one has internet connection (falling back to pen&paper, otherwise). +- *Searchable*, one has to be able to search and filter the pile of notes. +- *Out of the way*, sophistication will only get in the way of recording one's thoughts. + +`joyce` is structured as a small tool written in Rust running on a server, loosely inspired by [`twtxt`](https://github.com/buckket/twtxt). +Clients interface themselves with the server through a simple REST API. + +# Notes + +Notes are the first-class citizen of `joyce` and are the main content exchanged between server and clients. + +Notes, along with their REST API are defined in their own module + +```{#main_mods .rust} +mod note; +``` + +```{#note.rs .rust path="src/"} +<> + +<> + +<> + +<> +``` + +## Anatomy of a note + +A *note* is a simple structure recording a timestamp determined at creation, a list of tags, and the body of the note. + +```{#note_struct .rust} +#[derive(Debug, Deserialize, Serialize)] +pub struct Note { + timestamp: DateTime, + tags: Vec, + body: String, +} + +<> +``` + +```{#note_impl .rust} +impl Note { + fn new(body: String, tags: Vec) -> Self { + Self { timestamp: Utc::now(), tags, body } + } +} +``` + +A set of notes is just a `Vec` of `Note`s. + +```{#note_collection .rust} +type Notes = Vec; +``` + +### (De)serialization + +Since notes need to be sent and received via HTTP, the structure needs to be *serializable*. + +```{#dependencies .toml} +serde = { version = "1.0", features = ["derive"] } +``` + +```{#note_uses .rust} +use serde::{Serialize, Deserialize}; +``` + +### Timestamps + +Timestamps adhere the *RFC 3339 date-time standard* with UTC offset. + +```{#dependencies .toml} +chrono = { version = "0.4", features = ["serde"] } +``` + +```{#note_uses .rust} +use chrono::prelude::{DateTime, Utc}; +``` + +# The REST API + +`joyce` uses [`actix-web`](https://actix.rs/) to handle HTTP requests and responses. + +```{#dependencies .toml} +actix-web = "4.1" +``` + +## Resources + +- [Tutorial](https://web.archive.org/web/20220710213947/https://hub.qovery.com/guides/tutorial/create-a-blazingly-fast-api-in-rust-part-1/) +- [Introduction to `actix`](https://actix.rs/docs/getting-started/) + + +## GET /notes + +Each request handlers is an *async* function that accepts zero or more parameters, extracted from a request (see [`FromRequest`](https://docs.rs/actix-web/latest/actix_web/trait.FromRequest.html) trait), and returns an [`HttpResponse`](https://docs.rs/actix-web/latest/actix_web/struct.HttpResponse.html). + +Here we are requesting the list of notes currently in the system. +The function takes 0 parameters and returns a JSON object. + +```{#note_uses .rust} +use actix_web::{HttpResponse,get}; +use actix_web::http::header::ContentType; +``` + +```{#req_get_notes .rust} +#[get("/notes")] +pub async fn list() -> HttpResponse { + let mut notes: Notes = vec![]; + + <> + + HttpResponse::Ok() + .content_type(ContentType::json()) + .json(notes) +} +``` + +# The program + +The main program is structured as follows + +```{#main.rs .rust path="src/"} +<> + +<> + +<> +``` + +# Main service + +The main service will instantiate a new `App` running within a `HttpServer` bound to *localhost* on port 8080. + +```{#main_uses .rust} +use actix_web::{App, HttpServer}; +``` + +The `App` will register all request handlers defined above. + +```{#main_service .rust} +#[actix_web::main] +async fn main() -> std::io::Result<()> { + HttpServer::new(|| { + App::new() + .service(note::list) + }) + .bind(("127.0.0.1", 8080))? + .run() + .await +} +``` + +# Testing + +```{#notes_retrieve .rust} +notes.push(Note::new( + String::from("This is a first test note!"), + vec![String::from("test"), String::from("alpha"), String::from("literate")])); +notes.push(Note::new( + String::from("This is my favourite emoji: 🦥"), + vec![String::from("test"), String::from("emoji")])); +notes.push(Note::new( + String::from("Here is a link: https://www.federicoigne.com/"), + vec![String::from("test"), String::from("links")])); +``` +# Open questions + +- Should one be able to delete notes? Or mark them as read/processed? +- Authentication method? +- Custom filters on retrieval. + +# Credits + +`joyce v0.1.0` was created by Federico Igne ([git@federicoigne.com](mailto:git@federicoigne.com)) and available at [`https://git.dyamon.me/projects/joyce`](https://git.dyamon.me/projects/joyce). + +```{#Cargo.toml .toml} +[package] +name = "joyce" +version = "0.1.0" +edition = "2021" + +[dependencies] +<> +``` -- cgit v1.2.3