From 3cd10c9fc17d3c37bf8641daab16f1b138f81cf0 Mon Sep 17 00:00:00 2001 From: Kent Tristan Yves Sarmiento Date: Mon, 18 Dec 2023 14:26:13 +0800 Subject: [PATCH] feat: setup links service (#6) --- src/controller/links.rs | 32 +++++++++++++++-------------- src/lib.rs | 2 ++ src/repository.rs | 44 +--------------------------------------- src/repository/links.rs | 15 ++++++++++++++ src/repository/sample.rs | 12 ----------- src/router.rs | 17 ++++++++++------ src/service.rs | 1 + src/service/links.rs | 37 +++++++++++++++++++++++++++++++++ src/types.rs | 4 ++++ src/types/links.rs | 12 +++++++++++ src/types/repository.rs | 31 ++++++++++++++++++++++++++++ src/types/service.rs | 31 ++++++++++++++++++++++++++++ src/types/state.rs | 24 ++++++++++++++++++++++ 13 files changed, 186 insertions(+), 76 deletions(-) create mode 100644 src/repository/links.rs delete mode 100644 src/repository/sample.rs create mode 100644 src/service.rs create mode 100644 src/service/links.rs create mode 100644 src/types.rs create mode 100644 src/types/links.rs create mode 100644 src/types/repository.rs create mode 100644 src/types/service.rs create mode 100644 src/types/state.rs diff --git a/src/controller/links.rs b/src/controller/links.rs index 8c5a988..bb41aef 100644 --- a/src/controller/links.rs +++ b/src/controller/links.rs @@ -6,12 +6,12 @@ use axum::{ }; use serde_json::json; -use crate::repository::DynLinksRepo; +use crate::types::state::Router as RouterState; const LINKS_ROUTE: &str = "/v1/links"; const LINKS_ID_ROUTE: &str = "/v1/links/:id"; -pub fn router() -> Router { +pub fn router() -> Router { Router::new() .route(LINKS_ROUTE, routing::get(list)) .route(LINKS_ROUTE, routing::post(post)) @@ -20,8 +20,9 @@ pub fn router() -> Router { .route(LINKS_ID_ROUTE, routing::delete(delete)) } -async fn list(State(links_repo): State) -> impl IntoResponse { - match links_repo.list().await { +async fn list(State(app_state): State) -> impl IntoResponse { + let links_service = app_state.get_links_service(); + match links_service.list(&app_state).await { Ok(list) => Json(list).into_response(), Err(e) => { tracing::error!("Error: {}", e); @@ -34,8 +35,9 @@ async fn list(State(links_repo): State) -> impl IntoResponse { } } -async fn post(State(links_repo): State) -> impl IntoResponse { - match links_repo.post().await { +async fn post(State(app_state): State) -> impl IntoResponse { + let links_service = app_state.get_links_service(); + match links_service.post(&app_state).await { Ok(link) => Json(link).into_response(), Err(e) => { tracing::error!("Error: {}", e); @@ -48,8 +50,9 @@ async fn post(State(links_repo): State) -> impl IntoResponse { } } -async fn get(Path(id): Path, State(links_repo): State) -> impl IntoResponse { - match links_repo.get(&id).await { +async fn get(Path(id): Path, State(app_state): State) -> impl IntoResponse { + let links_service = app_state.get_links_service(); + match links_service.get(&id, &app_state).await { Ok(link) => Json(link).into_response(), Err(e) => { tracing::error!("Error: {}", e); @@ -62,8 +65,9 @@ async fn get(Path(id): Path, State(links_repo): State) -> } } -async fn put(Path(id): Path, State(links_repo): State) -> impl IntoResponse { - match links_repo.put(&id).await { +async fn put(Path(id): Path, State(app_state): State) -> impl IntoResponse { + let links_service = app_state.get_links_service(); + match links_service.put(&id, &app_state).await { Ok(link) => Json(link).into_response(), Err(e) => { tracing::error!("Error: {}", e); @@ -76,11 +80,9 @@ async fn put(Path(id): Path, State(links_repo): State) -> } } -async fn delete( - Path(id): Path, - State(links_repo): State, -) -> impl IntoResponse { - match links_repo.delete(&id).await { +async fn delete(Path(id): Path, State(app_state): State) -> impl IntoResponse { + let links_service = app_state.get_links_service(); + match links_service.delete(&id, &app_state).await { Ok(()) => StatusCode::NO_CONTENT.into_response(), Err(e) => { tracing::error!("Error: {}", e); diff --git a/src/lib.rs b/src/lib.rs index ebc56ae..95e5050 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,3 +4,5 @@ pub mod router; mod controller; mod repository; +mod service; +mod types; diff --git a/src/repository.rs b/src/repository.rs index ee8edb6..19b2f4d 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -1,43 +1 @@ -use std::sync::Arc; - -use axum::async_trait; -use serde::{Deserialize, Serialize}; - -pub mod sample; - -pub type DynLinksRepo = Arc; -type RepoResult = std::result::Result>; - -#[async_trait] -pub trait LinksRepo { - async fn list(&self) -> RepoResult> { - Err("Not implemented".into()) - } - - async fn post(&self) -> RepoResult { - Err("Not implemented".into()) - } - - async fn get(&self, _id: &str) -> RepoResult { - Err("Not implemented".into()) - } - - async fn put(&self, _id: &str) -> RepoResult { - Err("Not implemented".into()) - } - - async fn delete(&self, _id: &str) -> RepoResult<()> { - Err("Not implemented".into()) - } -} - -#[derive(Debug, Default, Serialize, Deserialize)] -pub struct ListItem { - id: String, - owner: String, - url: String, - title: String, - description: String, - created_at: String, - updated_at: String, -} +pub mod links; diff --git a/src/repository/links.rs b/src/repository/links.rs new file mode 100644 index 0000000..9a216c4 --- /dev/null +++ b/src/repository/links.rs @@ -0,0 +1,15 @@ +use axum::async_trait; + +use crate::types::{ + links::LinkItem, + repository::{Links, Result}, +}; + +pub struct Repository {} + +#[async_trait] +impl Links for Repository { + async fn list(&self) -> Result> { + Ok(vec![]) + } +} diff --git a/src/repository/sample.rs b/src/repository/sample.rs deleted file mode 100644 index d831269..0000000 --- a/src/repository/sample.rs +++ /dev/null @@ -1,12 +0,0 @@ -use axum::async_trait; - -use super::{LinksRepo, ListItem, RepoResult}; - -pub struct Repo {} - -#[async_trait] -impl LinksRepo for Repo { - async fn list(&self) -> RepoResult> { - Ok(vec![]) - } -} diff --git a/src/router.rs b/src/router.rs index a4abb31..ef792c6 100644 --- a/src/router.rs +++ b/src/router.rs @@ -1,11 +1,16 @@ use std::sync::Arc; -use axum::Router; +use crate::{ + controller, repository, service, + types::{repository::DynLinks as DynLinksRepo, service::DynLinks as DynLinksService, state}, +}; -use crate::controller::links; -use crate::repository::{sample, DynLinksRepo}; +pub fn new() -> axum::Router { + let links_repo = Arc::new(repository::links::Repository {}) as DynLinksRepo; + let links_service = Arc::new(service::links::Service {}) as DynLinksService; -pub fn new() -> Router { - let list_repo = Arc::new(sample::Repo {}) as DynLinksRepo; - Router::new().merge(links::router()).with_state(list_repo) + let state = state::Router::new(links_repo, links_service); + axum::Router::new() + .merge(controller::links::router()) + .with_state(state) } diff --git a/src/service.rs b/src/service.rs new file mode 100644 index 0000000..19b2f4d --- /dev/null +++ b/src/service.rs @@ -0,0 +1 @@ +pub mod links; diff --git a/src/service/links.rs b/src/service/links.rs new file mode 100644 index 0000000..8da40d5 --- /dev/null +++ b/src/service/links.rs @@ -0,0 +1,37 @@ +use axum::async_trait; + +use crate::types::{ + links::LinkItem, + service::{Links, Result}, + state, +}; + +pub struct Service {} + +#[async_trait] +impl Links for Service { + async fn list<'a>(&self, app_state: &'a state::Router) -> Result> { + let links_repo = app_state.get_links_repo(); + links_repo.list().await + } + + async fn post<'a>(&self, app_state: &'a state::Router) -> Result { + let links_repo = app_state.get_links_repo(); + links_repo.post().await + } + + async fn get<'a>(&self, id: &str, app_state: &'a state::Router) -> Result { + let links_repo = app_state.get_links_repo(); + links_repo.get(id).await + } + + async fn put<'a>(&self, id: &str, app_state: &'a state::Router) -> Result { + let links_repo = app_state.get_links_repo(); + links_repo.put(id).await + } + + async fn delete<'a>(&self, id: &str, app_state: &'a state::Router) -> Result<()> { + let links_repo = app_state.get_links_repo(); + links_repo.delete(id).await + } +} diff --git a/src/types.rs b/src/types.rs new file mode 100644 index 0000000..180b07b --- /dev/null +++ b/src/types.rs @@ -0,0 +1,4 @@ +pub mod links; +pub mod repository; +pub mod service; +pub mod state; diff --git a/src/types/links.rs b/src/types/links.rs new file mode 100644 index 0000000..2524d56 --- /dev/null +++ b/src/types/links.rs @@ -0,0 +1,12 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Default, Serialize, Deserialize)] +pub struct LinkItem { + id: String, + owner: String, + url: String, + title: String, + description: String, + created_at: String, + updated_at: String, +} diff --git a/src/types/repository.rs b/src/types/repository.rs new file mode 100644 index 0000000..4a2cd8d --- /dev/null +++ b/src/types/repository.rs @@ -0,0 +1,31 @@ +use std::sync::Arc; + +use axum::async_trait; + +use super::links::LinkItem; + +pub type DynLinks = Arc; +pub type Result = std::result::Result>; + +#[async_trait] +pub trait Links { + async fn list(&self) -> Result> { + Err("Not implemented".into()) + } + + async fn post(&self) -> Result { + Err("Not implemented".into()) + } + + async fn get(&self, _id: &str) -> Result { + Err("Not implemented".into()) + } + + async fn put(&self, _id: &str) -> Result { + Err("Not implemented".into()) + } + + async fn delete(&self, _id: &str) -> Result<()> { + Err("Not implemented".into()) + } +} diff --git a/src/types/service.rs b/src/types/service.rs new file mode 100644 index 0000000..e27ac8a --- /dev/null +++ b/src/types/service.rs @@ -0,0 +1,31 @@ +use std::sync::Arc; + +use axum::async_trait; + +use super::{links::LinkItem, state}; + +pub type DynLinks = Arc; +pub type Result = std::result::Result>; + +#[async_trait] +pub trait Links { + async fn list<'a>(&self, _app_state: &'a state::Router) -> Result> { + Err("Not implemented".into()) + } + + async fn post<'a>(&self, _app_state: &'a state::Router) -> Result { + Err("Not implemented".into()) + } + + async fn get<'a>(&self, _id: &str, _app_state: &'a state::Router) -> Result { + Err("Not implemented".into()) + } + + async fn put<'a>(&self, _id: &str, _app_state: &'a state::Router) -> Result { + Err("Not implemented".into()) + } + + async fn delete<'a>(&self, _id: &str, _app_state: &'a state::Router) -> Result<()> { + Err("Not implemented".into()) + } +} diff --git a/src/types/state.rs b/src/types/state.rs new file mode 100644 index 0000000..83f54bf --- /dev/null +++ b/src/types/state.rs @@ -0,0 +1,24 @@ +use super::{repository::DynLinks as DynLinksRepo, service::DynLinks as DynLinksService}; + +#[derive(Clone)] +pub struct Router { + links_repo: DynLinksRepo, + links_service: DynLinksService, +} + +impl Router { + pub fn new(links_repo: DynLinksRepo, links_service: DynLinksService) -> Self { + Self { + links_repo, + links_service, + } + } + + pub fn get_links_repo(&self) -> &DynLinksRepo { + &self.links_repo + } + + pub fn get_links_service(&self) -> &DynLinksService { + &self.links_service + } +}