This commit is contained in:
2021-09-07 20:26:59 +02:00
parent 1f905f5934
commit 7a4a27823b
7 changed files with 178 additions and 159 deletions

View File

@@ -1,7 +1,7 @@
[package] [package]
name = "packager-api" name = "packager-api"
version = "0.1.0" version = "0.1.0"
edition = "2018" edition = "2021"
[lib] [lib]
name = "packager" name = "packager"

25
api/README.md Normal file
View File

@@ -0,0 +1,25 @@
# Setup
* Install `rustup`
On Arch Linux:
```
$ sudo pacman -S rustup
```
```
$ rustup toolchain install nightly
```
# Run Dev
```
$ rustup run nightly cargo run
```
# Build
```
$ rustup run nightly cargo build --release
```

View File

@@ -1,12 +1,14 @@
use uuid::Uuid; use uuid::Uuid;
pub mod packagelist; pub mod packagelist;
pub use packagelist::PackageList;
pub use packagelist::PackageItem; pub use packagelist::PackageItem;
// use self::packagelist; pub use packagelist::PackageList;
pub mod router; pub mod router;
// pub use crate::packager::packagelist;
pub mod trip;
pub use trip::Trip;
pub use trip::TripList;
pub fn get_list(id: Uuid) -> Option<packagelist::PackageList> { pub fn get_list(id: Uuid) -> Option<packagelist::PackageList> {
println!("Looking for id {}", id); println!("Looking for id {}", id);
@@ -21,6 +23,21 @@ pub fn get_list(id: Uuid) -> Option<packagelist::PackageList> {
None None
} }
pub fn get_trips() -> Vec<Trip> {
let package_lists = get_lists();
vec![
Trip::from_package_list(
Uuid::parse_str("98dd50f9-b945-48e0-8fa9-41a3fd8b897e").unwrap(),
String::from("Campingtrip"),
String::from("2021-09-06"),
vec![
package_lists[0].id,
package_lists[1].id,
],
)
]
}
pub fn get_lists() -> Vec<packagelist::PackageList> { pub fn get_lists() -> Vec<packagelist::PackageList> {
vec![ vec![
packagelist::PackageList::new_from_items( packagelist::PackageList::new_from_items(

View File

@@ -1,139 +1,38 @@
use packager; use packager;
use uuid::Uuid;
#[derive(Debug)]
enum TripItemStatus {
Pending,
Ready,
Packed,
}
#[derive(Debug)]
struct TripItem<'a> {
package_item: &'a packager::PackageItem,
status: TripItemStatus,
}
impl TripItem<'_> {
fn from_package_item(package_item: &packager::PackageItem) -> TripItem {
TripItem {
package_item,
status: TripItemStatus::Pending,
}
}
fn set_status(&mut self, status: TripItemStatus) {
self.status = status;
}
}
#[derive(Debug)]
struct TripList<'a> {
items: Vec<TripItem<'a>>,
}
impl<'a> TripList<'a> {
fn from_package_list(list: &'a packager::PackageList) -> TripList<'a> {
let mut items = Vec::new();
for item in &list.items {
items.push(TripItem::from_package_item(item));
}
TripList { items }
}
}
#[derive(Debug)]
struct Trip<'a> {
name: String,
date: String,
list: TripList<'a>,
}
impl<'a> Trip<'a> {
fn from_package_list(name: String, date: String, list: &'a packager::PackageList) -> Trip<'a> {
Trip {
name,
date,
list: TripList::from_package_list(list),
}
}
}
// for list in &lists {
// println!("Contents of package list {:?}:", list.name);
// for item in &list.items {
// println!("\t{:?}", item);
// }
// }
// println!("\nNow we're starting an actual trip!");
// let mut trip = Trip::from_package_list(
// String::from("Campingtrip"),
// String::from("2021-09-06"),
// &lists[0],
// );
// println!(
// "\nPackage list for trip {:?} at {:?}:",
// trip.name, trip.date
// );
// for item in &trip.list.items {
// println!("{:?}", item);
// }
// trip.list.items[0].set_status(TripItemStatus::Ready);
// trip.list.items[1].set_status(TripItemStatus::Packed);
// for item in &trip.list.items {
// println!("{:?}", item);
// }
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
// let accept_json = warp::header::exact("accept", "application/json"); // let lists = packager::get_lists();
// let cors = warp::cors().allow_any_origin();
// let root = warp::path::end() // for list in &lists {
// .map(|| "Hi") // println!("Contents of package list {:?}:", list.name);
// .recover(packager::router::handle_rejection); // for item in &list.items {
// println!("\t{:?}", item);
// }
// }
// let v1 = warp::path!("v1") // println!("\nNow we're starting an actual trip!");
// .and(warp::get())
// .and(warp::path::end())
// .map(warp::reply)
// .recover(packager::router::handle_rejection);
// let lists = warp::path!("v1" / "lists") // let mut trip = packager::trip::Trip::from_package_list(
// .and(warp::path::end()) // String::from("Campingtrip"),
// .and(warp::get()) // String::from("2021-09-06"),
// .and(accept_json) // &lists[0],
// .map(|| warp::reply::json(&packager::get_lists())) // );
// .with(&cors)
// .recover(packager::router::handle_rejection);
// let list = warp::path!("v1" / "lists" / String) // println!(
// .and(warp::path::end()) // "\nPackage list for trip {:?} at {:?}:",
// .and(warp::get()) // trip.name, trip.date
// .and(accept_json) // );
// .and_then(|id: String| async move { // for item in &trip.list.items {
// match Uuid::parse_str(&id) { // println!("{:?}", item);
// Ok(uuid) => { // }
// let list = &packager::get_list(uuid);
// match list {
// Some(l) => Ok(warp::reply::json(l)),
// None => Err(warp::reject::not_found()),
// }
// }
// Err(e) => Err(warp::reject::custom(packager::router::InvalidUuid)),
// }
// })
// .with(&cors)
// .recover(packager::router::handle_rejection);
// let router = root.or(v1).or(lists).or(list); // trip.list.items[0].set_status(packager::trip::TripItemStatus::Ready);
// trip.list.items[1].set_status(packager::trip::TripItemStatus::Packed);
// for item in &trip.list.items {
// println!("{:?}", item);
// }
let router = packager::router::new(); let router = packager::router::new();
warp::serve(router).run(([127, 0, 0, 1], 9000)).await; warp::serve(router).run(([127, 0, 0, 1], 9000)).await;
} }

View File

@@ -1,9 +1,9 @@
use serde::ser::{SerializeStruct, Serializer}; use serde::ser::{SerializeStruct, Serializer};
use serde::{Deserialize, Serialize}; use serde::{Serialize};
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum Duration { pub enum Duration {
None, None,
@@ -16,8 +16,7 @@ impl Duration {
} }
} }
#[derive(Debug, Deserialize)] #[derive(Debug)]
#[serde(rename_all = "camelCase")]
pub enum Period { pub enum Period {
Daily(i32), Daily(i32),
Weekly(i32), Weekly(i32),
@@ -52,8 +51,7 @@ impl Serialize for Period {
} }
} }
#[derive(Debug, Deserialize)] #[derive(Debug)]
#[serde(rename_all = "camelCase")]
pub enum ItemUsage { pub enum ItemUsage {
Singleton, Singleton,
Periodic(Period), Periodic(Period),
@@ -86,9 +84,7 @@ impl Serialize for ItemUsage {
} }
} }
#[derive(Debug)]
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum ItemSize { pub enum ItemSize {
None, None,
Pack(i32), Pack(i32),
@@ -135,7 +131,7 @@ impl ItemSize {
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PreparationStep { pub struct PreparationStep {
name: String, name: String,
@@ -150,7 +146,7 @@ impl PreparationStep {
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub enum Preparation { pub enum Preparation {
None, None,
@@ -163,8 +159,7 @@ impl Preparation {
} }
} }
#[derive(Debug, Serialize)]
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PackageItem { pub struct PackageItem {
pub id: Uuid, pub id: Uuid,
@@ -210,7 +205,7 @@ impl PackageItem {
} }
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
pub struct PackageList { pub struct PackageList {
pub id: Uuid, pub id: Uuid,
@@ -223,4 +218,3 @@ impl PackageList {
PackageList { id, name, items } PackageList { id, name, items }
} }
} }

View File

@@ -1,7 +1,10 @@
use std::convert::Infallible;
use serde::Serialize; use serde::Serialize;
use std::convert::Infallible;
use warp; use warp;
use warp::http::StatusCode; use warp::http::StatusCode;
use warp::Filter;
use uuid::Uuid; use uuid::Uuid;
#[derive(Debug)] #[derive(Debug)]
@@ -20,23 +23,19 @@ pub fn new() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
let accept_json = warp::header::exact("accept", "application/json"); let accept_json = warp::header::exact("accept", "application/json");
let cors = warp::cors().allow_any_origin(); let cors = warp::cors().allow_any_origin();
let root = warp::path::end() let root = warp::path::end().map(|| "Hi");
.map(|| "Hi")
.recover(handle_rejection);
let v1 = warp::path!("v1") let v1 = warp::path!("v1")
.and(warp::get()) .and(warp::get())
.and(warp::path::end()) .and(warp::path::end())
.map(warp::reply) .map(warp::reply);
.recover(handle_rejection);
let lists = warp::path!("v1" / "lists") let lists = warp::path!("v1" / "lists")
.and(warp::path::end()) .and(warp::path::end())
.and(warp::get()) .and(warp::get())
.and(accept_json) .and(accept_json)
.map(|| warp::reply::json(&super::get_lists())) .map(|| warp::reply::json(&super::get_lists()))
.with(&cors) .with(&cors);
.recover(handle_rejection);
let list = warp::path!("v1" / "lists" / String) let list = warp::path!("v1" / "lists" / String)
.and(warp::path::end()) .and(warp::path::end())
@@ -51,15 +50,24 @@ pub fn new() -> warp::filters::BoxedFilter<(impl warp::Reply,)> {
None => Err(warp::reject::not_found()), None => Err(warp::reject::not_found()),
} }
} }
Err(e) => Err(warp::reject::custom(InvalidUuid)), Err(_) => Err(warp::reject::custom(InvalidUuid)),
} }
}) })
.with(&cors) .with(&cors);
.recover(handle_rejection);
let routes = root.or(v1).or(lists).or(list).boxed(); let trips = warp::path!("v1" / "trips")
.and(warp::path::end())
.and(warp::get())
.and(accept_json)
.map(|| warp::reply::json(&super::get_trips()))
.with(&cors);
routes root.or(v1)
.or(lists)
.or(list)
.or(trips)
.recover(handle_rejection)
.boxed()
} }
// See https://github.com/seanmonstar/warp/blob/master/examples/rejections.rs // See https://github.com/seanmonstar/warp/blob/master/examples/rejections.rs
@@ -73,7 +81,7 @@ async fn handle_rejection(err: warp::Rejection) -> Result<impl warp::Reply, Infa
} else if let Some(InvalidUuid) = err.find() { } else if let Some(InvalidUuid) = err.find() {
code = StatusCode::BAD_REQUEST; code = StatusCode::BAD_REQUEST;
message = "INVALID_UUID"; message = "INVALID_UUID";
} else if let Some(e) = err.find::<warp::filters::body::BodyDeserializeError>() { } else if let Some(_) = err.find::<warp::filters::body::BodyDeserializeError>() {
message = "BAD_REQUEST"; message = "BAD_REQUEST";
code = StatusCode::BAD_REQUEST; code = StatusCode::BAD_REQUEST;
} else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() { } else if let Some(_) = err.find::<warp::reject::MethodNotAllowed>() {

76
api/src/trip.rs Normal file
View File

@@ -0,0 +1,76 @@
use uuid::Uuid;
use serde::{Serialize};
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub enum TripItemStatus {
Pending,
Ready,
Packed,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TripItem<'a> {
pub id: Uuid,
pub package_item: &'a super::PackageItem,
pub status: TripItemStatus,
}
impl TripItem<'_> {
pub fn from_package_item(id: Uuid, package_item: &super::PackageItem) -> TripItem {
TripItem {
id,
package_item,
status: TripItemStatus::Pending,
}
}
pub fn set_status(&mut self, status: TripItemStatus) {
self.status = status;
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct TripList<'a> {
pub id: Uuid,
pub items: Vec<TripItem<'a>>,
}
impl<'a> TripList<'a> {
pub fn from_package_list(id: Uuid, list: &'a super::PackageList) -> TripList<'a> {
let mut items = Vec::new();
for item in &list.items {
items.push(TripItem::from_package_item(Uuid::new_v4(), item));
}
TripList { id, items }
}
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Trip {
pub id: Uuid,
pub name: String,
pub date: String,
pub package_list_ids: Vec<Uuid>,
}
impl Trip {
pub fn from_package_list(
id: Uuid,
name: String,
date: String,
package_list_ids: Vec<Uuid>,
) -> Trip {
Trip {
id,
name,
date,
package_list_ids,
}
}
}