Skip to content

Commit

Permalink
add axum
Browse files Browse the repository at this point in the history
  • Loading branch information
soulww committed Jan 30, 2024
1 parent 3e51618 commit f41d003
Show file tree
Hide file tree
Showing 13 changed files with 614 additions and 4 deletions.
9 changes: 9 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,15 @@ serde_with = { version = "3.4.0" }
serde_json = "1.0"
serde_yaml = "0.9.27"

axum = {version = "0.7.4"}
axum-macros = {version = "0.4.1"}
http-body-util = {version = "0.1.0"}

case = {version = "1.0"}
rust-format = {version = "0.3.4"}
tera = {version = "1.19"}


thiserror = {version = "1.0"}
path-absolutize = { version = "3.1.1"}
typetag = { version= "0.2"}
Expand Down
15 changes: 14 additions & 1 deletion luna-orm-axum/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,17 @@ version.workspace = true
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
axum = {version = "0.7.4"}
#sqlx = {workspace = true}
axum = {workspace = true}
axum-macros = {workspace = true}
tokio = {workspace = true}
serde = {workspace = true}
serde_yaml = {workspace = true}
serde_json = {workspace = true}
case = {workspace = true}
rust-format = {workspace = true}
tera = {workspace = true}
http-body-util = {workspace = true}

sqlx = {version = "0.7.3", features = ["runtime-tokio", "mysql", "sqlite", "macros", "any"]}
luna-orm = { path = "../luna-orm", version = "0.3.6" }
68 changes: 68 additions & 0 deletions luna-orm-axum/src/field_type.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use serde::{Deserialize, Serialize};

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum NumericType {
#[serde(alias = "short")]
Short,
#[serde(alias = "int")]
Integer,
#[serde(alias = "long")]
Long,

#[serde(alias = "ushort")]
UShort,
#[serde(alias = "uint")]
UInteger,
#[serde(alias = "ulong")]
ULong,

#[serde(alias = "float")]
Float,
#[serde(alias = "double")]
Double,
#[serde(alias = "decimal")]
Decimal,
}

#[derive(Debug, Clone, Deserialize, Serialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum FieldType {
#[serde(alias = "boolean")]
Boolean,

#[serde(alias = "timestamp")]
Timestamp,

#[serde(alias = "datetime")]
DateTime,

#[serde(alias = "uuid")]
Uuid,

#[serde(alias = "id")]
Id,

#[serde(alias = "string")]
String,

#[serde(alias = "cellphone")]
Cellphone,

#[serde(alias = "email")]
Email,

#[serde(untagged)]
NumericType(NumericType),
}

#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_deserialize() {
let field_type: FieldType = serde_yaml::from_str("ushort").unwrap();
let expect_type: FieldType = FieldType::NumericType(NumericType::UShort);
assert_eq!(field_type, expect_type);
}
}
20 changes: 20 additions & 0 deletions luna-orm-axum/src/generator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use crate::Schema;

pub struct Generator {
schema: Schema,
}

impl Generator {
pub fn new(schema: Schema) -> Self {
Self { schema }
}

pub fn from_yaml<T: AsRef<str>>(value: T) -> serde_yaml::Result<Self> {
let schema = serde_yaml::from_str(value.as_ref())?;
Ok(Generator::new(schema))
}

pub fn generate_axum_router() -> String {
"".to_string()
}
}
220 changes: 220 additions & 0 deletions luna-orm-axum/src/handler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,220 @@
use std::future::Future;

use crate::request::*;
use crate::response::*;
use axum::extract::FromRequest;
use axum::extract::Request;
use axum::extract::State;
use axum::handler::Handler;
use axum::http::Result;
use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::response::Response;
use axum::Json;
use axum::Router;
use axum_macros::debug_handler;
use http_body_util::BodyExt;
use luna_orm::prelude::*;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use std::marker::PhantomData;
use std::pin::Pin;

/*
struct ResponseSuccess<T> {
success: bool,
data: T
}
struct ResponseFailure {
success: bool,
err_code: i16,
err_msg: String
}
enum Response<T> {
Success(ResultSuccess<T>),
Failure(ResultFailure)
}
type Result<T> = std::result::Result<Response<T>, thiserror::Error>
enum InsertRequest {
}
// POST /users
insert(State(database), Json(entity)) -> Result<()>
// POST /users
create(State(database), Json(entity)) -> Result<entity>
// POST /users
upsert(State(database), Json(entity)) -> Result<()>
// PUT /users
update(State(database), Json(UpdateRequest)) -> Result<()>
// PUT /users
change(State(database), Json(ChangeRequest)) -> Result<usize>
// DELETE /users
delete(State(database), Json(primary)) -> Result<()>
// DELETE /users
remove(State(database), Json(primary)) -> Result<entity>
// DELETE /users
purify(State(database), Json(location)) -> Result<usize>
*/

//#[debug_handler]
pub async fn post<D, T>(
State(mut db): State<DB<D>>,
Json(payload): Json<PostRequest<T>>,
) -> Result<Json<PostResponse<T>>>
where
T: Serialize + Entity + Send + Sync,
D: Database,
{
match payload {
PostRequest::Create { mut entity } => {
db.create(&mut entity).await.unwrap();
let response = PostResponse::Create { entity };
Ok(Json(response))
}
PostRequest::Insert { entity } => {
db.insert(&entity).await.unwrap();
Ok(Json(PostResponse::Insert))
}
PostRequest::Upsert { entity } => {
db.upsert(&entity).await.unwrap();
Ok(Json(PostResponse::Insert))
}
}
}

#[derive(Clone, Debug)]
pub struct PostHandler<D, T>
where
D: Database + Clone + Send + 'static,
T: DeserializeOwned + Entity + Send + Clone + 'static,
{
db: PhantomData<D>,
data: PhantomData<T>,
}

impl<D, T> Default for PostHandler<D, T>
where
D: Database + Clone + Send + 'static,
T: DeserializeOwned + Entity + Send + Clone + 'static,
{
fn default() -> Self {
Self {
db: PhantomData,
data: PhantomData,
}
}
}

impl<S, T> Handler<((),), S> for PostHandler<S, T>
where
S: Database + Clone + Send + 'static,
T: DeserializeOwned + Entity + Send + Clone + 'static,
{
type Future = Pin<Box<dyn Future<Output = Response> + Send>>;

fn call(self, req: Request, state: S) -> Self::Future {
Box::pin(async move {
let (mut parts, body) = req.into_parts();
let data = body.collect().await.unwrap().to_bytes();
let payload: PostRequest<T> = serde_json::from_slice(&data).unwrap();
post_test(payload).await;

let response: Response = StatusCode::NOT_FOUND.into_response();
response
})
}
}

pub async fn post_test<T>(payload: PostRequest<T>) -> bool
where
T: Entity + Send + Sync,
{
true
/*
match payload {
PostRequest::Create { mut entity } => {
db.create(&mut entity).await.unwrap();
let response = PostResponse::Create { entity };
Ok(Json(response))
}
PostRequest::Insert { entity } => {
db.insert(&entity).await.unwrap();
Ok(Json(PostResponse::Insert))
}
PostRequest::Upsert { entity } => {
db.upsert(&entity).await.unwrap();
Ok(Json(PostResponse::Insert))
}
}
*/
}
pub async fn put<D, M, P, L>(
State(mut db): State<DB<D>>,
Json(payload): Json<PutRequest<M, P, L>>,
) -> Result<Json<PutResponse>>
where
M: Serialize + Mutation,
P: Serialize + Primary,
L: Serialize + Location,
D: Database,
{
match payload {
PutRequest::Update { mutation, primary } => {
db.update(&mutation, &primary).await.unwrap();
let response = PutResponse::Update;
Ok(Json(response))
}
PutRequest::Change { mutation, location } => {
let count = db.change(&mutation, &location).await.unwrap();
Ok(Json(PutResponse::Change { count }))
}
}
}

pub async fn delete<D, P, L, S, SE>(
State(mut db): State<DB<D>>,
Json(payload): Json<DeleteRequest<P, L, S>>,
) -> Result<Json<DeleteResponse<SE>>>
where
P: Serialize + Primary,
L: Serialize + Location,
S: Serialize + Selection,
SE: Serialize + SelectedEntity + Send + Unpin,
D: Database,
{
match payload {
DeleteRequest::Delete { primary } => {
db.delete(&primary).await.unwrap();
let response = DeleteResponse::Delete;
Ok(Json(response))
}
DeleteRequest::Remove { primary, selection } => {
let entity: Option<SE> = db.remove(&primary, &selection).await.unwrap();
Ok(Json(DeleteResponse::Remove { entity }))
}
DeleteRequest::Purify { location } => {
let count = db.purify(&location).await.unwrap();
Ok(Json(DeleteResponse::Purify { count }))
}
}
}

pub fn generate_router<D, P, E>(path: P)
where
P: AsRef<str>,
D: Database,
E: Entity + Serialize,
{
/*
let router = Router::new().route(
path.as_ref(),
axum::routing::post(post::<SqliteDatabase, E>),
);
*/
}
10 changes: 10 additions & 0 deletions luna-orm-axum/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
mod field_type;
mod generator;
pub mod handler;
pub mod request;
pub mod response;
pub mod router;
mod schema;

pub use field_type::FieldType;
pub use schema::*;
3 changes: 0 additions & 3 deletions luna-orm-axum/src/main.rs

This file was deleted.

Loading

0 comments on commit f41d003

Please sign in to comment.