aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFederico Igne <git@federicoigne.com>2022-07-26 22:53:37 +0100
committerFederico Igne <git@federicoigne.com>2022-07-26 22:53:37 +0100
commit32f54b51afe153546d87f86a0e260486dcb17355 (patch)
treec96e2ce4a66a22e31c12a7da3d3cbc34f22ee891
downloadjoyce-32f54b51afe153546d87f86a0e260486dcb17355.tar.gz
joyce-32f54b51afe153546d87f86a0e260486dcb17355.zip
feat(GET /notes): add first implementation for notes retrieval
-rw-r--r--README.md196
1 files changed, 196 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..1e36c2d
--- /dev/null
+++ b/README.md
@@ -0,0 +1,196 @@
1---
2title: joyce - record your thoughts as they come
3author: Federico Igne
4date: \today
5---
6
7`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.
8
9On a high-level, this system should be:
10
11- *Hubiquitous*, needs to be available (read/write) whenever one has internet connection (falling back to pen&paper, otherwise).
12- *Searchable*, one has to be able to search and filter the pile of notes.
13- *Out of the way*, sophistication will only get in the way of recording one's thoughts.
14
15`joyce` is structured as a small tool written in Rust running on a server, loosely inspired by [`twtxt`](https://github.com/buckket/twtxt).
16Clients interface themselves with the server through a simple REST API.
17
18# Notes
19
20Notes are the first-class citizen of `joyce` and are the main content exchanged between server and clients.
21
22Notes, along with their REST API are defined in their own module
23
24```{#main_mods .rust}
25mod note;
26```
27
28```{#note.rs .rust path="src/"}
29<<note_uses>>
30
31<<note_struct>>
32
33<<note_impl>>
34
35<<req_get_notes>>
36```
37
38## Anatomy of a note
39
40A *note* is a simple structure recording a timestamp determined at creation, a list of tags, and the body of the note.
41
42```{#note_struct .rust}
43#[derive(Debug, Deserialize, Serialize)]
44pub struct Note {
45 timestamp: DateTime<Utc>,
46 tags: Vec<String>,
47 body: String,
48}
49
50<<note_collection>>
51```
52
53```{#note_impl .rust}
54impl Note {
55 fn new(body: String, tags: Vec<String>) -> Self {
56 Self { timestamp: Utc::now(), tags, body }
57 }
58}
59```
60
61A set of notes is just a `Vec` of `Note`s.
62
63```{#note_collection .rust}
64type Notes = Vec<Note>;
65```
66
67### (De)serialization
68
69Since notes need to be sent and received via HTTP, the structure needs to be *serializable*.
70
71```{#dependencies .toml}
72serde = { version = "1.0", features = ["derive"] }
73```
74
75```{#note_uses .rust}
76use serde::{Serialize, Deserialize};
77```
78
79### Timestamps
80
81Timestamps adhere the *RFC 3339 date-time standard* with UTC offset.
82
83```{#dependencies .toml}
84chrono = { version = "0.4", features = ["serde"] }
85```
86
87```{#note_uses .rust}
88use chrono::prelude::{DateTime, Utc};
89```
90
91# The REST API
92
93`joyce` uses [`actix-web`](https://actix.rs/) to handle HTTP requests and responses.
94
95```{#dependencies .toml}
96actix-web = "4.1"
97```
98
99## Resources
100
101- [Tutorial](https://web.archive.org/web/20220710213947/https://hub.qovery.com/guides/tutorial/create-a-blazingly-fast-api-in-rust-part-1/)
102- [Introduction to `actix`](https://actix.rs/docs/getting-started/)
103
104
105## GET /notes
106
107Each 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).
108
109Here we are requesting the list of notes currently in the system.
110The function takes 0 parameters and returns a JSON object.
111
112```{#note_uses .rust}
113use actix_web::{HttpResponse,get};
114use actix_web::http::header::ContentType;
115```
116
117```{#req_get_notes .rust}
118#[get("/notes")]
119pub async fn list() -> HttpResponse {
120 let mut notes: Notes = vec![];
121
122 <<notes_retrieve>>
123
124 HttpResponse::Ok()
125 .content_type(ContentType::json())
126 .json(notes)
127}
128```
129
130# The program
131
132The main program is structured as follows
133
134```{#main.rs .rust path="src/"}
135<<main_uses>>
136
137<<main_mods>>
138
139<<main_service>>
140```
141
142# Main service
143
144The main service will instantiate a new `App` running within a `HttpServer` bound to *localhost* on port 8080.
145
146```{#main_uses .rust}
147use actix_web::{App, HttpServer};
148```
149
150The `App` will register all request handlers defined above.
151
152```{#main_service .rust}
153#[actix_web::main]
154async fn main() -> std::io::Result<()> {
155 HttpServer::new(|| {
156 App::new()
157 .service(note::list)
158 })
159 .bind(("127.0.0.1", 8080))?
160 .run()
161 .await
162}
163```
164
165# Testing
166
167```{#notes_retrieve .rust}
168notes.push(Note::new(
169 String::from("This is a first test note!"),
170 vec![String::from("test"), String::from("alpha"), String::from("literate")]));
171notes.push(Note::new(
172 String::from("This is my favourite emoji: 🦥"),
173 vec![String::from("test"), String::from("emoji")]));
174notes.push(Note::new(
175 String::from("Here is a link: https://www.federicoigne.com/"),
176 vec![String::from("test"), String::from("links")]));
177```
178# Open questions
179
180- Should one be able to delete notes? Or mark them as read/processed?
181- Authentication method?
182- Custom filters on retrieval.
183
184# Credits
185
186`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).
187
188```{#Cargo.toml .toml}
189[package]
190name = "joyce"
191version = "0.1.0"
192edition = "2021"
193
194[dependencies]
195<<dependencies>>
196```