From 67d554ce2b3a1177f970d90e86fef26d5e5def88 Mon Sep 17 00:00:00 2001 From: Federico Igne Date: Wed, 24 Aug 2022 21:38:27 +0100 Subject: feat(cli): add customizable parameters through CLI --- README.md | 119 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 104 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index c2f62bc..5ef21a8 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,86 @@ On a high-level, this system should be: `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. + +# Installation and setup + + + +## Command Line Interface + +`joyce` offers a very simple command line interface. +For an overview of the functionalities offered by the tool run + +```sh +joyce --help +``` + +`joyce` uses the `clap` library to parse command line arguments + +```{#dependencies .toml} +clap = { version = "3.1", features = ["derive"] } +``` + +```{#main_uses .rust} +use clap::Parser; +``` + +using the [Derive API](https://github.com/clap-rs/clap/blob/v3.1.18/examples/tutorial_derive/README.md) to define the exposed functionalities. +The `struct` holding the CLI information is defined as follow + +```{#main_config .rust} +/// Record your thoughts as they come. +#[derive(Parser, Debug)] +#[clap(author, version, about, long_about = None)] +struct Config { + <> + <> +} +``` + +and the arguments are parsed as + +```{#config_parse .rust} +let config = Config::parse(); +``` + +`joyce` assumes a SQLite database named `notes.db` is present in the current working directory. + +```{#main_constants .rust} +const DB: &str = "./notes.db"; +``` + +A custom path to a SQLite database can be passed using the `-d/--database` flag. + +```{#main_uses .rust} +use std::path::PathBuf; +``` + +```{#config_db .rust} +/// SQLite database [default: './notes.db'] +#[clap(short, long)] +database: Option, +``` + +Once started, `joyce` will be available on localhost (`127.0.0.1`) at port `8080`. + +```{#main_constants .rust} +const ADDR: &str = "127.0.0.1"; +const PORT: u16 = 8080; +``` + +This behaviour can be overridden with the `-a`/`--address` and `-p`/`--port` flags + +```{#config_address .rust} +/// Address the `joyce` service is bound to [default: '127.0.0.1'] +#[clap(short, long)] +address: Option, +/// Port the `joyce` service is bound to [default: 8080] +#[clap(short, long)] +port: Option, +``` + + # Notes Notes are the first-class citizen of `joyce` and are the main content exchanged between server and clients. @@ -243,6 +323,7 @@ rusqlite = { version = "0.28", features = ["chrono","serde_json"] } The following code sets up a connection pool to the SQLite database. ```{#db_uses .rust} +use std::path::Path; use r2d2_sqlite::SqliteConnectionManager; ``` @@ -251,9 +332,9 @@ pub type Pool = r2d2::Pool; ``` ```{#db_connection_pool .rust} -pub fn get_connection_pool(db: &str) -> Pool { +pub fn get_connection_pool>(db: P) -> Pool { let manager = SqliteConnectionManager::file(db); - r2d2::Pool::new(manager).expect("Unable to connect to 'notes.db'") + r2d2::Pool::new(manager).expect("Unable to connect to {db}") } ``` @@ -367,17 +448,21 @@ The `App` will register all request handlers defined above as *services*. ```{#main_service .rust} #[actix_web::main] async fn main() -> std::io::Result<()> { - let db_pool = db::get_connection_pool("notes.db"); - HttpServer::new(move || { - App::new() - .app_data(web::Data::new(db_pool.clone())) - .service(note::get_notes) - .service(note::get_tags) - .service(note::post_notes) - }) - .bind(("127.0.0.1", 8080))? - .run() - .await + <> + let addr = config.address.unwrap_or_else(|| ADDR.to_string()); + let port = config.port.unwrap_or(PORT); + let db_file = config.database.unwrap_or_else(|| PathBuf::from(DB)); + let db_pool = db::get_connection_pool(db_file); + HttpServer::new(move || { + App::new() + .app_data(web::Data::new(db_pool.clone())) + .service(note::get_notes) + .service(note::get_tags) + .service(note::post_notes) + }) + .bind((addr, port))? + .run() + .await } ``` @@ -391,6 +476,10 @@ mod db; <> +<> + +<> + <> ``` @@ -429,11 +518,11 @@ Communication with SQLite is grouped under the `db` module. # TODOs - Better error handling -- CLI with `clap` +- Logging +- add examples with cURL ## Open questions -- logging capabilities - Should one be able to delete notes? Or mark them as read/processed? - Authentication method? - Custom filters on retrieval. -- cgit v1.2.3