Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: setup links repository #5

Merged
merged 7 commits into from
Dec 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ axum = "0.7.2"
#lambda_http = "0.8.3"
lambda_http = { git = "https://github.com/awslabs/aws-lambda-rust-runtime", branch = "hyper1_upgrade" }
lambda_runtime = "0.8.3"
serde = { version = "1.0.193", features = [ "derive" ] }
serde_json = "1.0.108"
tokio = { version = "1", features = ["macros"] }
tracing = { version = "0.1", features = ["log"] }
Expand Down
18 changes: 13 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Required Downloads:

- Docker
- Visual Studio Code
- [Devcontainer extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)
- [Devcontainer extension for vscode](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers)

Setup:

Expand All @@ -29,8 +29,16 @@ Setup:

1. Wait for notification in the bottom right corner asking to `"Reopen in container"`.

[Cargo Lambda](https://www.cargo-lambda.info/) is used for development of this service and it is pre-installed as part of the devcontainer. Use [Cargo Lambda Watch](https://www.cargo-lambda.info/commands/watch.html) to hotcompile your changes:
Testing:

```sh
cargo lambda watch
```
1. [cargo lambda](https://www.cargo-lambda.info/) is used for development of this service and it is pre-installed as part of the devcontainer. Use [cargo lambda watch](https://www.cargo-lambda.info/commands/watch.html) to hotcompile your changes:

```sh
cargo lambda watch
```

1. [cargo clippy](https://github.com/rust-lang/rust-clippy) is used for linting to catch common errors. This is setup to run on saving changes in the devcontainer. You may also run it from bash using the following command:

```sh
cargo clippy --all-targets --all-features -- -D warnings
```
2 changes: 1 addition & 1 deletion src/controller.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pub mod link;
pub mod links;
22 changes: 0 additions & 22 deletions src/controller/link.rs

This file was deleted.

94 changes: 94 additions & 0 deletions src/controller/links.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use axum::{
extract::{Path, State},
http::StatusCode,
response::{IntoResponse, Json},
routing, Router,
};
use serde_json::json;

use crate::repository::DynLinksRepo;

const LINKS_ROUTE: &str = "/v1/links";
const LINKS_ID_ROUTE: &str = "/v1/links/:id";

pub fn router() -> Router<DynLinksRepo> {
Router::new()
.route(LINKS_ROUTE, routing::get(list))
.route(LINKS_ROUTE, routing::post(post))
.route(LINKS_ID_ROUTE, routing::get(get))
.route(LINKS_ID_ROUTE, routing::put(put))
.route(LINKS_ID_ROUTE, routing::delete(delete))
}

async fn list(State(links_repo): State<DynLinksRepo>) -> impl IntoResponse {
match links_repo.list().await {
Ok(list) => Json(list).into_response(),
Err(e) => {
tracing::error!("Error: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ "msg": e.to_string() })),
)
.into_response()
}
}
}

async fn post(State(links_repo): State<DynLinksRepo>) -> impl IntoResponse {
match links_repo.post().await {
Ok(link) => Json(link).into_response(),
Err(e) => {
tracing::error!("Error: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ "msg": e.to_string() })),
)
.into_response()
}
}
}

async fn get(Path(id): Path<String>, State(links_repo): State<DynLinksRepo>) -> impl IntoResponse {
match links_repo.get(&id).await {
Ok(link) => Json(link).into_response(),
Err(e) => {
tracing::error!("Error: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ "msg": e.to_string() })),
)
.into_response()
}
}
}

async fn put(Path(id): Path<String>, State(links_repo): State<DynLinksRepo>) -> impl IntoResponse {
match links_repo.put(&id).await {
Ok(link) => Json(link).into_response(),
Err(e) => {
tracing::error!("Error: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ "msg": e.to_string() })),
)
.into_response()
}
}
}

async fn delete(
Path(id): Path<String>,
State(links_repo): State<DynLinksRepo>,
) -> impl IntoResponse {
match links_repo.delete(&id).await {
Ok(()) => StatusCode::NO_CONTENT.into_response(),
Err(e) => {
tracing::error!("Error: {}", e);
(
StatusCode::INTERNAL_SERVER_ERROR,
Json(json!({ "msg": e.to_string() })),
)
.into_response()
}
}
}
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
pub mod router;

mod controller;
mod repository;
43 changes: 43 additions & 0 deletions src/repository.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use std::sync::Arc;

use axum::async_trait;
use serde::{Deserialize, Serialize};

pub mod sample;

pub type DynLinksRepo = Arc<dyn LinksRepo + Send + Sync>;
type RepoResult<T> = std::result::Result<T, Box<dyn std::error::Error>>;

#[async_trait]
pub trait LinksRepo {
async fn list(&self) -> RepoResult<Vec<ListItem>> {
Err("Not implemented".into())
}

async fn post(&self) -> RepoResult<ListItem> {
Err("Not implemented".into())
}

async fn get(&self, _id: &str) -> RepoResult<ListItem> {
Err("Not implemented".into())
}

async fn put(&self, _id: &str) -> RepoResult<ListItem> {
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,
}
12 changes: 12 additions & 0 deletions src/repository/sample.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use axum::async_trait;

use super::{LinksRepo, ListItem, RepoResult};

pub struct Repo {}

#[async_trait]
impl LinksRepo for Repo {
async fn list(&self) -> RepoResult<Vec<ListItem>> {
Ok(vec![])
}
}
15 changes: 7 additions & 8 deletions src/router.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use axum::{routing::get, Router};
use std::sync::Arc;

use crate::controller::link;
use axum::Router;

use crate::controller::links;
use crate::repository::{sample, DynLinksRepo};

pub fn new() -> Router {
Router::new()
.route("/link", get(link::list).post(link::post))
.route(
"/link/:id",
get(link::get).put(link::put).delete(link::delete),
)
let list_repo = Arc::new(sample::Repo {}) as DynLinksRepo;
Router::new().merge(links::router()).with_state(list_repo)
}
Loading