Compare commits

..

2 Commits

16 changed files with 237 additions and 308 deletions

1
.env Normal file
View File

@ -0,0 +1 @@
DATABASE_URL=sqlite://mydb.db

1
.gitignore vendored
View File

@ -1 +1,2 @@
/target /target
*.db

335
Cargo.lock generated
View File

@ -163,12 +163,6 @@ dependencies = [
"windows-link", "windows-link",
] ]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.21.7" version = "0.21.7"
@ -199,12 +193,6 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bumpalo"
version = "3.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -361,27 +349,6 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
dependencies = [ dependencies = [
"block-buffer", "block-buffer",
"crypto-common", "crypto-common",
"subtle",
]
[[package]]
name = "dirs"
version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
"redox_users",
"winapi",
] ]
[[package]] [[package]]
@ -470,6 +437,18 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3" checksum = "0399f9d26e5191ce32c498bebd31e7a3ceabc2745f0ac54af3f335126c3f24b3"
[[package]]
name = "flume"
version = "0.10.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
dependencies = [
"futures-core",
"futures-sink",
"pin-project",
"spin",
]
[[package]] [[package]]
name = "fnv" name = "fnv"
version = "1.0.7" version = "1.0.7"
@ -522,6 +501,17 @@ version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
[[package]]
name = "futures-executor"
version = "0.3.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
dependencies = [
"futures-core",
"futures-task",
"futures-util",
]
[[package]] [[package]]
name = "futures-intrusive" name = "futures-intrusive"
version = "0.4.2" version = "0.4.2"
@ -556,6 +546,7 @@ dependencies = [
"futures-task", "futures-task",
"pin-project-lite", "pin-project-lite",
"pin-utils", "pin-utils",
"slab",
] ]
[[package]] [[package]]
@ -656,21 +647,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
[[package]] [[package]]
name = "hkdf" name = "hospital_server"
version = "0.12.4" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
dependencies = [ dependencies = [
"hmac", "axum",
] "config",
"dotenvy",
[[package]] "serde",
name = "hmac" "sqlx",
version = "0.12.1" "tokio",
source = "registry+https://github.com/rust-lang/crates.io-index" "tracing",
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" "tracing-subscriber",
dependencies = [ "utoipa",
"digest", "utoipa-axum",
"utoipa-scalar",
] ]
[[package]] [[package]]
@ -911,16 +901,6 @@ version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
[[package]]
name = "js-sys"
version = "0.3.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec48937a97411dcb524a265206ccd4c90bb711fca92b2792c407f268825b9305"
dependencies = [
"once_cell",
"wasm-bindgen",
]
[[package]] [[package]]
name = "json5" name = "json5"
version = "0.4.1" version = "0.4.1"
@ -945,14 +925,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
[[package]] [[package]]
name = "libredox" name = "libsqlite3-sys"
version = "0.1.10" version = "0.24.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" checksum = "898745e570c7d0453cc1fbc4a701eb6c662ed54e8fec8b7d14be137ebeeb9d14"
dependencies = [ dependencies = [
"bitflags 2.9.4", "cc",
"libc", "pkg-config",
"redox_syscall 0.5.18", "vcpkg",
] ]
[[package]] [[package]]
@ -988,16 +968,6 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
[[package]]
name = "md-5"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
dependencies = [
"cfg-if",
"digest",
]
[[package]] [[package]]
name = "memchr" name = "memchr"
version = "2.7.6" version = "2.7.6"
@ -1259,6 +1229,26 @@ dependencies = [
"sha2", "sha2",
] ]
[[package]]
name = "pin-project"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
version = "1.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
]
[[package]] [[package]]
name = "pin-project-lite" name = "pin-project-lite"
version = "0.2.16" version = "0.2.16"
@ -1286,15 +1276,6 @@ dependencies = [
"zerovec", "zerovec",
] ]
[[package]]
name = "ppv-lite86"
version = "0.2.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
dependencies = [
"zerocopy",
]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.101" version = "1.0.101"
@ -1319,36 +1300,6 @@ version = "5.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f"
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom 0.2.16",
]
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.16" version = "0.2.16"
@ -1367,24 +1318,13 @@ dependencies = [
"bitflags 2.9.4", "bitflags 2.9.4",
] ]
[[package]]
name = "redox_users"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom 0.2.16",
"libredox",
"thiserror",
]
[[package]] [[package]]
name = "ron" name = "ron"
version = "0.8.1" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [ dependencies = [
"base64 0.21.7", "base64",
"bitflags 2.9.4", "bitflags 2.9.4",
"serde", "serde",
"serde_derive", "serde_derive",
@ -1419,12 +1359,6 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "rustversion"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.20" version = "1.0.20"
@ -1556,17 +1490,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "sha1"
version = "0.10.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
[[package]] [[package]]
name = "sha2" name = "sha2"
version = "0.10.9" version = "0.10.9"
@ -1624,6 +1547,15 @@ dependencies = [
"windows-sys 0.59.0", "windows-sys 0.59.0",
] ]
[[package]]
name = "spin"
version = "0.9.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
dependencies = [
"lock_api",
]
[[package]] [[package]]
name = "sqlformat" name = "sqlformat"
version = "0.2.6" version = "0.2.6"
@ -1652,37 +1584,31 @@ checksum = "fa8241483a83a3f33aa5fff7e7d9def398ff9990b2752b6c6112b83c6d246029"
dependencies = [ dependencies = [
"ahash 0.7.8", "ahash 0.7.8",
"atoi", "atoi",
"base64 0.13.1",
"bitflags 1.3.2", "bitflags 1.3.2",
"byteorder", "byteorder",
"bytes", "bytes",
"crc", "crc",
"crossbeam-queue", "crossbeam-queue",
"dirs",
"dotenvy", "dotenvy",
"either", "either",
"event-listener", "event-listener",
"flume",
"futures-channel", "futures-channel",
"futures-core", "futures-core",
"futures-executor",
"futures-intrusive", "futures-intrusive",
"futures-util", "futures-util",
"hashlink 0.8.4", "hashlink 0.8.4",
"hex", "hex",
"hkdf",
"hmac",
"indexmap 1.9.3", "indexmap 1.9.3",
"itoa", "itoa",
"libc", "libc",
"libsqlite3-sys",
"log", "log",
"md-5",
"memchr", "memchr",
"once_cell", "once_cell",
"paste", "paste",
"percent-encoding", "percent-encoding",
"rand",
"serde",
"serde_json",
"sha1",
"sha2", "sha2",
"smallvec", "smallvec",
"sqlformat", "sqlformat",
@ -1691,7 +1617,6 @@ dependencies = [
"thiserror", "thiserror",
"tokio-stream", "tokio-stream",
"url", "url",
"whoami",
] ]
[[package]] [[package]]
@ -1742,12 +1667,6 @@ dependencies = [
"unicode-properties", "unicode-properties",
] ]
[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.109" version = "1.0.109"
@ -1800,22 +1719,6 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "test_exercise"
version = "0.1.0"
dependencies = [
"axum",
"config",
"serde",
"sqlx",
"tokio",
"tracing",
"tracing-subscriber",
"utoipa",
"utoipa-axum",
"utoipa-scalar",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.69" version = "1.0.69"
@ -2212,92 +2115,6 @@ dependencies = [
"wit-bindgen", "wit-bindgen",
] ]
[[package]]
name = "wasite"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
[[package]]
name = "wasm-bindgen"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1da10c01ae9f1ae40cbfac0bac3b1e724b320abfcf52229f80b547c0d250e2d"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "671c9a5a66f49d8a47345ab942e2cb93c7d1d0339065d4f8139c486121b43b19"
dependencies = [
"bumpalo",
"log",
"proc-macro2",
"quote",
"syn 2.0.106",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ca60477e4c59f5f2986c50191cd972e3a50d8a95603bc9434501cf156a9a119"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9f07d2f20d4da7b26400c9f4a0511e6e0345b040694e8a75bd41d578fa4421d7"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.106",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.104"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bad67dc8b2a1a6e5448428adec4c3e84c43e561d8c9ee8a9e5aabeb193ec41d1"
dependencies = [
"unicode-ident",
]
[[package]]
name = "web-sys"
version = "0.3.81"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9367c417a924a74cae129e6a2ae3b47fabb1f8995595ab474029da749a8be120"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]]
name = "whoami"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
dependencies = [
"libredox",
"wasite",
"web-sys",
]
[[package]] [[package]]
name = "winapi" name = "winapi"
version = "0.3.9" version = "0.3.9"

View File

@ -1,5 +1,5 @@
[package] [package]
name = "test_exercise" name = "hospital_server"
version = "0.1.0" version = "0.1.0"
edition = "2024" edition = "2024"
@ -9,10 +9,11 @@ edition = "2024"
axum = {version = "0.8.4", features = ["macros"]} axum = {version = "0.8.4", features = ["macros"]}
tokio = {version = "1.47.1", features = ["full"]} tokio = {version = "1.47.1", features = ["full"]}
utoipa = "5.4.0" utoipa = "5.4.0"
sqlx = {version = "0.6.0", features = ["runtime-tokio-native-tls","postgres"]} sqlx = {version = "0.6.0", features = ["runtime-tokio-native-tls","sqlite"]}
config = "0.15.6" config = "0.15.6"
utoipa-axum = {version = "0.2.0" } utoipa-axum = {version = "0.2.0" }
utoipa-scalar = { version = "0.3", features = ["axum"] } utoipa-scalar = { version = "0.3", features = ["axum"] }
tracing = "0.1.41" tracing = "0.1.41"
serde = "1.0.228" serde = "1.0.228"
tracing-subscriber = "0.3.20" tracing-subscriber = "0.3.20"
dotenvy = "0.15.7"

View File

@ -0,0 +1 @@
drop table "patients";

View File

@ -0,0 +1,5 @@
create table "patients" (
"id" INTEGER PRIMARY KEY,
"full_name" TEXT NOT NULL,
"phone" TEXT NOT NULL
);

View File

@ -0,0 +1,9 @@
insert into patients(
"full_name",
"phone"
)
values($1, $2)
returning
"id",
"full_name" as "full_name!",
"phone" as "phone!"

View File

@ -0,0 +1,3 @@
delete from patients
where id = $1
returning *;

1
queries/get_all.sql Normal file
View File

@ -0,0 +1 @@
select * from "patients"

View File

@ -0,0 +1,2 @@
select * from "patients"
where id = $1;

View File

@ -0,0 +1,3 @@
update patients
set full_name = $2, phone = $3
where id = $1;

6
src/app_state.rs Normal file
View File

@ -0,0 +1,6 @@
use sqlx::SqlitePool;
#[derive(Clone)]
pub struct AppState {
pub pool: SqlitePool,
}

View File

@ -1,63 +1,117 @@
use axum::{debug_handler, extract::Json, response::IntoResponse}; use axum::{
use schemas::Patient; Router, debug_handler,
use tracing::info; extract::{Json, Path, State},
use utoipa::{OpenApi, openapi::Response}; http::StatusCode,
response::IntoResponse,
};
use models::Patient;
use sqlx::{query_file, query_file_as};
use utoipa::OpenApi;
use utoipa_axum::{router::OpenApiRouter, routes}; use utoipa_axum::{router::OpenApiRouter, routes};
use crate::openapi::route_docs; use crate::{
app_state::AppState,
models::{CreatePatient, PathParams},
openapi::route_docs,
};
pub mod app_state;
pub mod models; pub mod models;
pub mod openapi; pub mod openapi;
pub mod schemas; pub mod schemas;
#[derive(Clone)]
struct AppState {}
#[derive(OpenApi)] #[derive(OpenApi)]
struct Api; struct Api;
pub async fn router() { pub fn router(state: AppState) -> Router {
let addr = "0.0.0.0:3000";
tracing_subscriber::fmt::init();
let (router, docs) = OpenApiRouter::with_openapi(Api::openapi()) let (router, docs) = OpenApiRouter::with_openapi(Api::openapi())
.routes(routes!(get_openapi)) .nest(
.routes(routes!(post_patient)) "/api/patients/",
.routes(routes!(get_patients)) OpenApiRouter::new()
.routes(routes!(update_patient_by_id)) .routes(routes!(create_patient, get_all))
.routes(routes!(delete_patient_by_id)) .routes(routes!(
update_patient_by_id,
delete_patient_by_id,
get_patient_by_id
)),
)
.with_state(state)
.split_for_parts(); .split_for_parts();
let listener = tokio::net::TcpListener::bind(addr).await.unwrap(); route_docs(router, docs)
info!("Listening in {:?}", listener.local_addr());
let router = route_docs(router, docs);
axum::serve(listener, router).await.unwrap();
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(get, path = "/api/patients", description="Get all patients", responses((status = OK, body = Patient)))] #[utoipa::path(get, path = "/", description="Get all patients", responses((status = OK, body = Patient)))]
async fn get_patients() -> impl IntoResponse { async fn get_all(State(state): State<AppState>) -> Json<Vec<Patient>> {
axum::http::StatusCode::NOT_IMPLEMENTED let patients = query_file_as!(Patient, "queries/get_all.sql")
.fetch_all(&state.pool)
.await
.expect("Could not fetch patients");
Json(patients)
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(get, path = "/api/openapi.json", description="Get openapi.json file", responses((status = OK)))] #[utoipa::path(get, path = "/{id}", description="Get all patients", responses((status = OK, body = Patient)))]
async fn get_openapi()-> impl IntoResponse { async fn get_patient_by_id(
axum::http::StatusCode::NOT_IMPLEMENTED State(state): State<AppState>,
Path(path): Path<PathParams>,
) -> impl IntoResponse {
let patient = query_file_as!(Patient, "queries/get_patient_by_id.sql", path.id)
.fetch_optional(&state.pool)
.await
.expect("Could not fetch patients");
match patient {
Some(p) => Json(p).into_response(),
None => StatusCode::NOT_FOUND.into_response(),
}
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(post, path = "/api/post_patient",description="Create a new patient", responses((status = OK)))] #[utoipa::path(post, path = "/", description = "Create a new patient", responses((status = OK)))]
async fn post_patient(Json(patient): Json<Patient>)-> impl IntoResponse { async fn create_patient(
axum::http::StatusCode::NOT_IMPLEMENTED State(state): State<AppState>,
Json(patient): Json<CreatePatient>,
) -> Json<Patient> {
let patient = query_file_as!(
Patient,
"queries/create_patient.sql",
patient.full_name,
patient.phone
)
.fetch_one(&state.pool)
.await
.expect("Could not create new patient");
Json(patient)
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(post, path = "/api/update_patiend_by_id",description="Update patient by ID", responses((status = OK)))] #[utoipa::path(post, path = "/{id}", description = "Update patient by ID", responses((status = OK)))]
async fn update_patient_by_id(Json(patient): Json<Patient>)-> impl IntoResponse { async fn update_patient_by_id(
axum::http::StatusCode::NOT_IMPLEMENTED State(state): State<AppState>,
Path(path): Path<PathParams>,
Json(patient): Json<CreatePatient>,
) -> impl IntoResponse {
query_file!(
"queries/update_patient.sql",
path.id,
patient.full_name,
patient.phone
)
.fetch_one(&state.pool)
.await
.expect("Could not create new patient");
StatusCode::CREATED
} }
#[debug_handler] #[debug_handler]
#[utoipa::path(delete, path = "/api/delete_patient_by_id", description="Delete patient by ID", responses((status = OK)))] #[utoipa::path(delete, path = "/{id}", description = "Delete patient by ID", responses((status = OK)))]
async fn delete_patient_by_id(Json(patinent): Json<Patient>)-> impl IntoResponse { async fn delete_patient_by_id(
axum::http::StatusCode::NOT_IMPLEMENTED State(state): State<AppState>,
Path(path): Path<PathParams>,
) -> impl IntoResponse {
query_file_as!(Patient, "queries/delete_patient.sql", path.id)
.fetch_one(&state.pool)
.await
.expect("Could not delete patient");
} }

View File

@ -1,6 +1,25 @@
use test_exercise::router; use hospital_server::app_state::AppState;
use hospital_server::router;
use sqlx::SqlitePool;
use tracing::info;
#[tokio::main] #[tokio::main]
async fn main() { async fn main() {
router().await; let _ = dotenvy::dotenv();
tracing_subscriber::fmt::init();
let db_url = std::env::var("DATABASE_URL").expect("DATABASE_URL is not set");
let pool = SqlitePool::connect(&db_url)
.await
.expect("Cannot connect to db");
sqlx::migrate!().run(&pool).await.unwrap();
let state = AppState { pool };
let router = router(state);
let addr = "0.0.0.0:3000";
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
info!("Listening in {:?}", listener.local_addr());
axum::serve(listener, router).await.unwrap();
} }

View File

@ -2,13 +2,19 @@ use serde::{Deserialize, Serialize};
use utoipa::ToSchema; use utoipa::ToSchema;
#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)] #[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
struct PatientId { pub struct Patient {
id: i32, pub id: i64,
pub full_name: String,
pub phone: String,
} }
#[derive(Debug, Clone, ToSchema, Serialize, Deserialize)] #[derive(Debug, Clone, ToSchema, Serialize, Deserialize)]
pub struct Patient { pub struct CreatePatient {
id: PatientId, pub full_name: String,
name: String, pub phone: String,
diagnosis: String, //todo! enum }
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PathParams {
pub id: i64,
} }

View File

@ -1,9 +1,9 @@
use axum::Router; use axum::{Router, routing::get};
use utoipa::openapi::OpenApi; use utoipa::openapi::OpenApi;
use utoipa_scalar::{Scalar, Servable}; use utoipa_scalar::{Scalar, Servable};
struct ApiDocs;
pub fn route_docs(router: Router, docs: OpenApi) -> Router { pub fn route_docs(router: Router, docs: OpenApi) -> Router {
router.merge(Scalar::with_url("/", docs)) router
.merge(Scalar::with_url("/", docs.clone()))
.route("/docs/openapi.json", get(docs.to_json().expect("serializing OpenAPI")))
} }