DieselCrud traits and derives
This commit is contained in:
parent
2c8577a11d
commit
ae775f4e9e
4
.idea/lib.iml
generated
4
.idea/lib.iml
generated
@ -9,6 +9,10 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/crates/read_files/src" isTestSource="false" />
|
<sourceFolder url="file://$MODULE_DIR$/crates/read_files/src" isTestSource="false" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/crates/read_files/tests" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/crates/read_files/tests" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/crates/read_files/tests" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/crates/read_files/tests" isTestSource="true" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/crates/diesel_crud_derive/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/crates/diesel_crud_trait/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/crates/tests/src" isTestSource="false" />
|
||||||
|
<sourceFolder url="file://$MODULE_DIR$/crates/tests/tests" isTestSource="true" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/target" />
|
<excludeFolder url="file://$MODULE_DIR$/target" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/examples/multipart_file/target" />
|
<excludeFolder url="file://$MODULE_DIR$/examples/multipart_file/target" />
|
||||||
|
852
Cargo.lock
generated
852
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
14
Cargo.toml
@ -4,7 +4,7 @@ exclude = ["examples"]
|
|||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.80.0"
|
rust-version = "1.80.1"
|
||||||
authors = ["Martin Berg Alstad"]
|
authors = ["Martin Berg Alstad"]
|
||||||
homepage = "emberal.github.io"
|
homepage = "emberal.github.io"
|
||||||
|
|
||||||
@ -25,8 +25,11 @@ axum = { version = "0.7", optional = true, features = ["multipart"] }
|
|||||||
tower = { version = "0.5", optional = true }
|
tower = { version = "0.5", optional = true }
|
||||||
tower-http = { version = "0.5", optional = true, features = ["trace", "cors", "normalize-path"] }
|
tower-http = { version = "0.5", optional = true, features = ["trace", "cors", "normalize-path"] }
|
||||||
# Async
|
# Async
|
||||||
tokio = { version = "1.38", optional = true, features = ["fs"] }
|
tokio = { version = "1.39", optional = true, features = ["fs"] }
|
||||||
tokio-util = { version = "0.7", optional = true, features = ["io"] }
|
tokio-util = { version = "0.7", optional = true, features = ["io"] }
|
||||||
|
# Database
|
||||||
|
diesel-crud-derive = { path = "crates/diesel_crud_derive", optional = true }
|
||||||
|
diesel-crud-trait = { path = "crates/diesel_crud_trait", optional = true }
|
||||||
# Error handling
|
# Error handling
|
||||||
thiserror = { version = "1.0", optional = true }
|
thiserror = { version = "1.0", optional = true }
|
||||||
# Logging
|
# Logging
|
||||||
@ -43,12 +46,17 @@ serde = { version = "1.0", optional = true, features = ["derive"] }
|
|||||||
[workspace.dependencies]
|
[workspace.dependencies]
|
||||||
syn = "2.0"
|
syn = "2.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
|
deluxe = "0.5"
|
||||||
|
proc-macro2 = "1.0"
|
||||||
|
diesel = "2.2"
|
||||||
|
diesel-async = "0.5"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
axum = ["dep:axum", "dep:tower", "dep:tower-http", "dep:thiserror", "dep:tracing", "dep:tracing-subscriber", "dep:tokio"]
|
axum = ["dep:axum", "dep:tower", "dep:tower-http", "dep:thiserror", "dep:tracing", "dep:tracing-subscriber", "dep:tokio"]
|
||||||
|
diesel = ["dep:diesel-crud-trait"]
|
||||||
io = ["dep:tokio", "dep:tokio-util"]
|
io = ["dep:tokio", "dep:tokio-util"]
|
||||||
iter = []
|
iter = []
|
||||||
nom = ["dep:nom"]
|
nom = ["dep:nom"]
|
||||||
serde = ["dep:serde"]
|
serde = ["dep:serde"]
|
||||||
derive = ["dep:into-response-derive", "axum", "serde"]
|
derive = ["dep:into-response-derive", "dep:diesel-crud-derive"]
|
||||||
read-files = ["dep:read-files"]
|
read-files = ["dep:read-files"]
|
||||||
|
2
Makefile
2
Makefile
@ -1,3 +1,3 @@
|
|||||||
fmt:
|
fmt:
|
||||||
cargo clippy --all-targets --all-features
|
cargo clippy --all-targets --all-features -- -D warnings
|
||||||
cargo fmt
|
cargo fmt
|
14
crates/diesel_crud_derive/Cargo.toml
Normal file
14
crates/diesel_crud_derive/Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "diesel-crud-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = { workspace = true }
|
||||||
|
rust-version = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = { workspace = true }
|
||||||
|
quote = { workspace = true }
|
||||||
|
deluxe = { workspace = true }
|
||||||
|
proc-macro2 = { workspace = true }
|
20
crates/diesel_crud_derive/src/common.rs
Normal file
20
crates/diesel_crud_derive/src/common.rs
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
use quote::quote;
|
||||||
|
|
||||||
|
pub(crate) fn function_body(body: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||||
|
quote! {
|
||||||
|
let connection = self.pool.get().await;
|
||||||
|
match connection {
|
||||||
|
Ok(mut connection) => {
|
||||||
|
use diesel::associations::HasTable;
|
||||||
|
#body
|
||||||
|
}
|
||||||
|
Err(error) => Err(lib::diesel_crud_trait::CrudError::PoolError(error.to_string())),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn return_type(output: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||||
|
quote! {
|
||||||
|
std::pin::Pin<Box<dyn core::future::Future<Output = Result<#output, lib::diesel_crud_trait::CrudError>> + Send + 'b>>
|
||||||
|
}
|
||||||
|
}
|
49
crates/diesel_crud_derive/src/create.rs
Normal file
49
crates/diesel_crud_derive/src/create.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use crate::{common, StructAttributes};
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::Expr;
|
||||||
|
|
||||||
|
pub(crate) fn derive_diesel_crud_create_impl(
|
||||||
|
StructAttributes {
|
||||||
|
table,
|
||||||
|
entity,
|
||||||
|
create,
|
||||||
|
..
|
||||||
|
}: &StructAttributes,
|
||||||
|
identifier: &Ident,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let body = function_body(table);
|
||||||
|
let return_type = common::return_type(quote! { Self::Entity });
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl<'insertable, 'entity> lib::diesel_crud_trait::DieselCrudCreate<'insertable, 'entity, #table::table> for #identifier
|
||||||
|
where
|
||||||
|
'entity: 'insertable,
|
||||||
|
{
|
||||||
|
type Create = #create;
|
||||||
|
type Entity = #entity;
|
||||||
|
fn create<'a, 'b>(&'a self, create: &'insertable Self::Create) -> #return_type
|
||||||
|
where
|
||||||
|
Self: Sync + 'a,
|
||||||
|
'a: 'b,
|
||||||
|
'insertable: 'b
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
#body
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_body(table: &Expr) -> proc_macro2::TokenStream {
|
||||||
|
common::function_body(quote! {
|
||||||
|
diesel_async::RunQueryDsl::get_result(
|
||||||
|
diesel::dsl::insert_into(#table::table::table()).values(create),
|
||||||
|
&mut connection
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
}
|
55
crates/diesel_crud_derive/src/delete.rs
Normal file
55
crates/diesel_crud_derive/src/delete.rs
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
use crate::{common, StructAttributes};
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use quote::{quote, ToTokens};
|
||||||
|
use syn::Expr;
|
||||||
|
|
||||||
|
pub(crate) fn derive_diesel_crud_delete_impl(
|
||||||
|
StructAttributes {
|
||||||
|
table,
|
||||||
|
pk,
|
||||||
|
pk_field,
|
||||||
|
..
|
||||||
|
}: &StructAttributes,
|
||||||
|
identifier: &Ident,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let body = function_body(
|
||||||
|
table,
|
||||||
|
pk_field
|
||||||
|
.clone()
|
||||||
|
.map(Expr::into_token_stream)
|
||||||
|
.unwrap_or_else(|| quote! { id }),
|
||||||
|
);
|
||||||
|
let return_type = common::return_type(quote! { usize });
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl lib::diesel_crud_trait::DieselCrudDelete for #identifier {
|
||||||
|
type PK = #pk;
|
||||||
|
fn delete<'a, 'pk, 'b>(&'a self, pk: &'pk Self::PK) -> #return_type
|
||||||
|
where
|
||||||
|
Self: Sync + 'a,
|
||||||
|
'a: 'b,
|
||||||
|
'pk: 'b,
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
#body
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_body(table: &Expr, pk_field: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||||
|
common::function_body(quote! {
|
||||||
|
use diesel::QueryDsl;
|
||||||
|
diesel_async::RunQueryDsl::execute(
|
||||||
|
diesel::delete(
|
||||||
|
#table::table
|
||||||
|
.filter(diesel::expression_methods::ExpressionMethods::eq(#table::#pk_field, pk))
|
||||||
|
),
|
||||||
|
&mut connection,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
}
|
183
crates/diesel_crud_derive/src/lib.rs
Normal file
183
crates/diesel_crud_derive/src/lib.rs
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
extern crate proc_macro;
|
||||||
|
|
||||||
|
use crate::create::derive_diesel_crud_create_impl;
|
||||||
|
use crate::delete::derive_diesel_crud_delete_impl;
|
||||||
|
use crate::list::derive_diesel_crud_list_impl;
|
||||||
|
use crate::read::derive_diesel_crud_read_impl;
|
||||||
|
use crate::update::derive_diesel_crud_update_impl;
|
||||||
|
use deluxe::{extract_attributes, ExtractAttributes};
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, DeriveInput, Expr, Type};
|
||||||
|
|
||||||
|
mod common;
|
||||||
|
mod create;
|
||||||
|
mod delete;
|
||||||
|
mod list;
|
||||||
|
mod read;
|
||||||
|
mod update;
|
||||||
|
|
||||||
|
#[derive(ExtractAttributes)]
|
||||||
|
#[deluxe(attributes(diesel_crud))]
|
||||||
|
pub(crate) struct StructAttributes {
|
||||||
|
table: Expr,
|
||||||
|
#[deluxe(default)]
|
||||||
|
entity: Option<Type>,
|
||||||
|
#[deluxe(default)]
|
||||||
|
pk: Option<Type>,
|
||||||
|
#[deluxe(default)]
|
||||||
|
pk_field: Option<Expr>,
|
||||||
|
#[deluxe(default)]
|
||||||
|
create: Option<Type>, // TODO if None, use entity?
|
||||||
|
#[deluxe(default)]
|
||||||
|
update: Option<Type>, // TODO if None, use entity?
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO get pool field automatically or by attribute
|
||||||
|
|
||||||
|
/// Derives 5 functions for CRUD operations
|
||||||
|
/// 1. create
|
||||||
|
/// 2. read
|
||||||
|
/// 3. update
|
||||||
|
/// 4. delete
|
||||||
|
/// 5. list
|
||||||
|
#[proc_macro_derive(DieselCrud, attributes(diesel_crud))]
|
||||||
|
pub fn derive_diesel_crud(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let mut item = parse_macro_input!(item as DeriveInput);
|
||||||
|
let struct_attributes = extract_attributes(&mut item).unwrap();
|
||||||
|
let identifier = item.ident;
|
||||||
|
|
||||||
|
let create = derive_diesel_crud_create_impl(&struct_attributes, &identifier);
|
||||||
|
let read = derive_diesel_crud_read_impl(&struct_attributes, &identifier);
|
||||||
|
let update = derive_diesel_crud_update_impl(&struct_attributes, &identifier);
|
||||||
|
let delete = derive_diesel_crud_delete_impl(&struct_attributes, &identifier);
|
||||||
|
let list = derive_diesel_crud_list_impl(&struct_attributes, &identifier);
|
||||||
|
|
||||||
|
let table = struct_attributes.table;
|
||||||
|
let expanded = quote! {
|
||||||
|
#create
|
||||||
|
#read
|
||||||
|
#update
|
||||||
|
#delete
|
||||||
|
#list
|
||||||
|
|
||||||
|
impl<'insertable, 'entity> lib::diesel_crud_trait::DieselCrud<'insertable, 'entity, #table::table> for #identifier
|
||||||
|
where
|
||||||
|
'entity: 'insertable
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
expanded.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the create function for CRUD operations.
|
||||||
|
/// Must be used on a struct with a field named `pool`, containing a `Pool<AsyncPgConnection>`.
|
||||||
|
/// # Struct Attributes
|
||||||
|
/// - table: Ident - The schema struct for the table
|
||||||
|
/// - result: Type - The resulting model
|
||||||
|
/// - create: Type - The insertable model
|
||||||
|
/// # Example
|
||||||
|
/// ```ignore
|
||||||
|
/// use diesel_async::{AsyncPgConnection, pooled_connection::deadpool::Pool};
|
||||||
|
///
|
||||||
|
/// #[derive(diesel_crud_derive::DieselCrudCreate)]
|
||||||
|
/// #[diesel_crud(table = crate::schema::user, result = crate::models::User, create = crate::models::InsertUser)]
|
||||||
|
/// struct TestServiceCreate {
|
||||||
|
/// pool: Pool<AsyncPgConnection>,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(DieselCrudCreate, attributes(diesel_crud))]
|
||||||
|
pub fn derive_diesel_crud_create(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let mut item = syn::parse_macro_input!(item as DeriveInput);
|
||||||
|
let struct_attributes = extract_attributes(&mut item).unwrap();
|
||||||
|
derive_diesel_crud_create_impl(&struct_attributes, &item.ident).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the read function for CRUD operations.
|
||||||
|
/// Must be used on a struct with a field named `pool`, containing a `Pool<AsyncPgConnection>`.
|
||||||
|
/// # Struct Attributes
|
||||||
|
/// - table: Ident - The schema struct for the table
|
||||||
|
/// - pk: Type - The primary key type
|
||||||
|
/// - result: Type - The resulting model
|
||||||
|
/// - pk_field (optional): Expr - The field to use as the primary key. Defaults to `id`
|
||||||
|
/// # Example
|
||||||
|
/// ```ignore
|
||||||
|
/// use diesel_async::{AsyncPgConnection, pooled_connection::deadpool::Pool};
|
||||||
|
///
|
||||||
|
/// #[derive(diesel_crud_derive::DieselCrudRead)]
|
||||||
|
/// #[diesel_crud(table = crate::schema::user, result = crate::models::User, pk = String)]
|
||||||
|
/// struct TestServiceRead {
|
||||||
|
/// pool: Pool<AsyncPgConnection>,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(DieselCrudRead, attributes(diesel_crud))]
|
||||||
|
pub fn derive_diesel_crud_read(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let mut item = syn::parse_macro_input!(item as DeriveInput);
|
||||||
|
let struct_attributes = extract_attributes(&mut item).unwrap();
|
||||||
|
derive_diesel_crud_read_impl(&struct_attributes, &item.ident).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the update function for CRUD operations.
|
||||||
|
/// Must be used on a struct with a field named `pool`, containing a `Pool<AsyncPgConnection>`.
|
||||||
|
/// # Struct Attributes
|
||||||
|
/// - table: Ident - The schema struct for the table
|
||||||
|
/// - update: Type - The update model
|
||||||
|
/// # Example
|
||||||
|
/// ```ignore
|
||||||
|
/// use diesel_async::{AsyncPgConnection, pooled_connection::deadpool::Pool};
|
||||||
|
///
|
||||||
|
/// #[derive(diesel_crud_derive::DieselCrudUpdate)]
|
||||||
|
/// #[diesel_crud(table = crate::schema::user, update = crate::models::User)]
|
||||||
|
/// struct TestServiceUpdate {
|
||||||
|
/// pool: Pool<AsyncPgConnection>,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(DieselCrudUpdate, attributes(diesel_crud))]
|
||||||
|
pub fn derive_diesel_crud_update(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let mut item = syn::parse_macro_input!(item as DeriveInput);
|
||||||
|
let struct_attributes = extract_attributes(&mut item).unwrap();
|
||||||
|
derive_diesel_crud_update_impl(&struct_attributes, &item.ident).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the delete function for CRUD operations.
|
||||||
|
/// Must be used on a struct with a field named `pool`, containing a `Pool<AsyncPgConnection>`.
|
||||||
|
/// # Struct Attributes
|
||||||
|
/// - table: Ident - The schema struct for the table
|
||||||
|
/// - pk: Type - The primary key type
|
||||||
|
/// - pk_field (optional): Expr - The field to use as the primary key. Defaults to `id`
|
||||||
|
/// # Example
|
||||||
|
/// ```ignore
|
||||||
|
/// use diesel_async::{AsyncPgConnection, pooled_connection::deadpool::Pool};
|
||||||
|
///
|
||||||
|
/// #[derive(diesel_crud_derive::DieselCrudDelete)]
|
||||||
|
/// #[diesel_crud(table = crate::schema::user, pk = String)]
|
||||||
|
/// struct TestServiceDelete {
|
||||||
|
/// pool: Pool<AsyncPgConnection>,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(DieselCrudDelete, attributes(diesel_crud))]
|
||||||
|
pub fn derive_diesel_crud_delete(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let mut item = syn::parse_macro_input!(item as DeriveInput);
|
||||||
|
let struct_attributes = extract_attributes(&mut item).unwrap();
|
||||||
|
derive_diesel_crud_delete_impl(&struct_attributes, &item.ident).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Derives the list function for CRUD operations.
|
||||||
|
/// Must be used on a struct with a field named `pool`, containing a `Pool<AsyncPgConnection>`.
|
||||||
|
/// # Struct Attributes
|
||||||
|
/// - table: Ident - The schema struct for the table
|
||||||
|
/// - result: Type - The resulting model
|
||||||
|
/// # Example
|
||||||
|
/// ```ignore
|
||||||
|
/// use diesel_async::{AsyncPgConnection, pooled_connection::deadpool::Pool};
|
||||||
|
///
|
||||||
|
/// #[derive(diesel_crud_derive::DieselCrudList)]
|
||||||
|
/// #[diesel_crud(table = crate::schema::user, result = crate::models::User)]
|
||||||
|
/// struct TestServiceList {
|
||||||
|
/// pool: Pool<AsyncPgConnection>,
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
#[proc_macro_derive(DieselCrudList, attributes(diesel_crud))]
|
||||||
|
pub fn derive_diesel_crud_list(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
|
let mut item = syn::parse_macro_input!(item as DeriveInput);
|
||||||
|
let struct_attributes = extract_attributes(&mut item).unwrap();
|
||||||
|
derive_diesel_crud_list_impl(&struct_attributes, &item.ident).into()
|
||||||
|
}
|
35
crates/diesel_crud_derive/src/list.rs
Normal file
35
crates/diesel_crud_derive/src/list.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
use proc_macro2::Ident;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::Expr;
|
||||||
|
|
||||||
|
use crate::{common, StructAttributes};
|
||||||
|
|
||||||
|
pub(crate) fn derive_diesel_crud_list_impl(
|
||||||
|
StructAttributes { table, entity, .. }: &StructAttributes,
|
||||||
|
identifier: &Ident,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let body = function_body(table);
|
||||||
|
let return_type = common::return_type(quote! { Vec<Self::Entity> });
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl lib::diesel_crud_trait::DieselCrudList for #identifier {
|
||||||
|
type Entity = #entity;
|
||||||
|
fn list<'a, 'b>(&'a self) -> #return_type
|
||||||
|
where
|
||||||
|
Self: Sync + 'a,
|
||||||
|
'a: 'b
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
#body
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_body(table: &Expr) -> proc_macro2::TokenStream {
|
||||||
|
common::function_body(quote! {
|
||||||
|
diesel_async::RunQueryDsl::get_results(#table::table::table(), &mut connection).await.map_err(Into::into)
|
||||||
|
})
|
||||||
|
}
|
38
crates/diesel_crud_derive/src/read.rs
Normal file
38
crates/diesel_crud_derive/src/read.rs
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
use proc_macro2::Ident;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::Expr;
|
||||||
|
|
||||||
|
use crate::{common, StructAttributes};
|
||||||
|
|
||||||
|
pub(crate) fn derive_diesel_crud_read_impl(
|
||||||
|
StructAttributes {
|
||||||
|
table, entity, pk, ..
|
||||||
|
}: &StructAttributes,
|
||||||
|
identifier: &Ident,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let body = function_body(table);
|
||||||
|
let return_type = common::return_type(quote! { Self::Entity });
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl lib::diesel_crud_trait::DieselCrudRead for #identifier {
|
||||||
|
type PK = #pk;
|
||||||
|
type Entity = #entity;
|
||||||
|
fn read<'a, 'b>(&'a self, pk: Self::PK) -> #return_type
|
||||||
|
where
|
||||||
|
Self: Sync + 'a,
|
||||||
|
'a: 'b
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
#body
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_body(table: &Expr) -> proc_macro2::TokenStream {
|
||||||
|
common::function_body(quote! {
|
||||||
|
diesel_async::RunQueryDsl::get_result(diesel::QueryDsl::find(#table::table::table(), pk), &mut connection).await.map_err(Into::into)
|
||||||
|
})
|
||||||
|
}
|
39
crates/diesel_crud_derive/src/update.rs
Normal file
39
crates/diesel_crud_derive/src/update.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use crate::{common, StructAttributes};
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::Expr;
|
||||||
|
|
||||||
|
pub(crate) fn derive_diesel_crud_update_impl(
|
||||||
|
StructAttributes { table, update, .. }: &StructAttributes,
|
||||||
|
identifier: &Ident,
|
||||||
|
) -> proc_macro2::TokenStream {
|
||||||
|
let body = function_body(table);
|
||||||
|
let return_type = common::return_type(quote! { usize });
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
#[automatically_derived]
|
||||||
|
impl lib::diesel_crud_trait::DieselCrudUpdate for #identifier {
|
||||||
|
type Update = #update;
|
||||||
|
fn update<'a, 'b>(&'a self, update: Self::Update) -> #return_type
|
||||||
|
where
|
||||||
|
Self: Sync + 'a,
|
||||||
|
'a: 'b,
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
#body
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn function_body(table: &Expr) -> proc_macro2::TokenStream {
|
||||||
|
common::function_body(quote! {
|
||||||
|
diesel_async::RunQueryDsl::execute(
|
||||||
|
diesel::dsl::update(#table::table::table()).set(update),
|
||||||
|
&mut connection,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
|
}
|
12
crates/diesel_crud_trait/Cargo.toml
Normal file
12
crates/diesel_crud_trait/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "diesel-crud-trait"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = { workspace = true }
|
||||||
|
rust-version = { workspace = true }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
diesel = { workspace = true, features = ["postgres"] }
|
||||||
|
diesel-async = { workspace = true, features = ["postgres", "deadpool"] }
|
||||||
|
async-trait = "0.1"
|
||||||
|
deadpool-diesel = { version = "0.6", features = ["postgres"] }
|
||||||
|
thiserror = "1.0"
|
22
crates/diesel_crud_trait/src/error.rs
Normal file
22
crates/diesel_crud_trait/src/error.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use diesel::result::Error;
|
||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
/// Error type for CRUD operations
|
||||||
|
#[derive(Debug, Error)]
|
||||||
|
pub enum CrudError {
|
||||||
|
#[error("Resource not found")]
|
||||||
|
NotFound,
|
||||||
|
#[error("Database pool error: {0}")]
|
||||||
|
PoolError(String),
|
||||||
|
#[error(transparent)]
|
||||||
|
Other(Error),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<Error> for CrudError {
|
||||||
|
fn from(error: Error) -> Self {
|
||||||
|
match error {
|
||||||
|
Error::NotFound => CrudError::NotFound,
|
||||||
|
_ => CrudError::Other(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
102
crates/diesel_crud_trait/src/lib.rs
Normal file
102
crates/diesel_crud_trait/src/lib.rs
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
mod error;
|
||||||
|
|
||||||
|
pub use error::CrudError;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
|
use diesel::{AsChangeset, Insertable};
|
||||||
|
|
||||||
|
pub trait DieselCrud<'insertable, 'entity, Table>:
|
||||||
|
DieselCrudCreate<'insertable, 'entity, Table>
|
||||||
|
+ DieselCrudRead
|
||||||
|
+ DieselCrudUpdate
|
||||||
|
+ DieselCrudDelete
|
||||||
|
+ DieselCrudList
|
||||||
|
where
|
||||||
|
'entity: 'insertable,
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Insert an entity into the database
|
||||||
|
/// The entity must implement `Insertable<Table>` for the given table.
|
||||||
|
///
|
||||||
|
/// Implementing the trait requires the `async_trait` macro.
|
||||||
|
/// # Associations
|
||||||
|
/// - `Create` - The type to insert
|
||||||
|
/// - `Entity` - The type that will be returned
|
||||||
|
/// # Parameters
|
||||||
|
/// - `create` - The entity to insert
|
||||||
|
/// # Returns
|
||||||
|
/// A result containing the inserted entity or a `CrudError`
|
||||||
|
#[async_trait]
|
||||||
|
pub trait DieselCrudCreate<'insertable, 'entity, Table>
|
||||||
|
where
|
||||||
|
'entity: 'insertable,
|
||||||
|
{
|
||||||
|
type Create: Insertable<Table>;
|
||||||
|
type Entity: 'entity;
|
||||||
|
async fn create(&self, create: &'insertable Self::Create) -> Result<Self::Entity, CrudError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets an entity from the database
|
||||||
|
///
|
||||||
|
/// Implementing the trait requires the `async_trait` macro.
|
||||||
|
/// # Associations
|
||||||
|
/// - `PK` - The primary key of the entity
|
||||||
|
/// - `Entity` - The type that will be returned
|
||||||
|
/// # Parameters
|
||||||
|
/// - `pk` - The primary key of the entity
|
||||||
|
/// # Returns
|
||||||
|
/// A result containing the entity or a `CrudError`.
|
||||||
|
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
||||||
|
#[async_trait]
|
||||||
|
pub trait DieselCrudRead {
|
||||||
|
type PK;
|
||||||
|
type Entity;
|
||||||
|
async fn read(&self, pk: Self::PK) -> Result<Self::Entity, CrudError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates an entity in the database
|
||||||
|
/// The entity must implement `AsChangeset` for the given table.
|
||||||
|
///
|
||||||
|
/// Implementing the trait requires the `async_trait` macro.
|
||||||
|
/// # Associations
|
||||||
|
/// - `Update` - The type to update
|
||||||
|
/// # Parameters
|
||||||
|
/// - `update` - The update to apply
|
||||||
|
/// # Returns
|
||||||
|
/// A result containing the number of rows updated or a `CrudError`.
|
||||||
|
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
||||||
|
#[async_trait]
|
||||||
|
pub trait DieselCrudUpdate {
|
||||||
|
type Update: AsChangeset;
|
||||||
|
async fn update(&self, update: Self::Update) -> Result<usize, CrudError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes an entity from the database
|
||||||
|
///
|
||||||
|
/// Implementing the trait requires the `async_trait` macro.
|
||||||
|
/// # Associations
|
||||||
|
/// - `PK` - The primary key of the entity
|
||||||
|
/// # Parameters
|
||||||
|
/// - `pk` - The primary key of the entity
|
||||||
|
/// # Returns
|
||||||
|
/// A result containing the number of rows deleted or a `CrudError`.
|
||||||
|
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
||||||
|
#[async_trait]
|
||||||
|
pub trait DieselCrudDelete {
|
||||||
|
type PK;
|
||||||
|
async fn delete(&self, pk: &Self::PK) -> Result<usize, CrudError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Lists all entities in the table
|
||||||
|
///
|
||||||
|
/// Implementing the trait requires the `async_trait` macro.
|
||||||
|
/// # Associations
|
||||||
|
/// - `Entity` - The type that will be returned in a Vec
|
||||||
|
/// # Returns
|
||||||
|
/// A result containing a Vec of entities or a `CrudError`.
|
||||||
|
#[async_trait]
|
||||||
|
pub trait DieselCrudList {
|
||||||
|
type Entity;
|
||||||
|
async fn list(&self) -> Result<Vec<Self::Entity>, CrudError>;
|
||||||
|
}
|
12
crates/tests/Cargo.toml
Normal file
12
crates/tests/Cargo.toml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "tests"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition.workspace = true
|
||||||
|
rust-version.workspace = true
|
||||||
|
authors.workspace = true
|
||||||
|
homepage.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
diesel = { workspace = true }
|
||||||
|
diesel-async = { workspace = true }
|
||||||
|
lib = { path = "../../../lib", features = ["diesel", "derive"] }
|
1
crates/tests/src/lib.rs
Normal file
1
crates/tests/src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
// This file is needed to make the tests directory a crate
|
82
crates/tests/tests/diesel_crud_derive.rs
Normal file
82
crates/tests/tests/diesel_crud_derive.rs
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
#![allow(unused)]
|
||||||
|
use diesel::{AsChangeset, Insertable, Queryable, Selectable};
|
||||||
|
use diesel_async::pooled_connection::deadpool::Pool;
|
||||||
|
use diesel_async::pooled_connection::AsyncDieselConnectionManager;
|
||||||
|
use diesel_async::AsyncPgConnection;
|
||||||
|
use lib::diesel_crud_derive::{
|
||||||
|
DieselCrud, DieselCrudCreate, DieselCrudDelete, DieselCrudList, DieselCrudRead,
|
||||||
|
DieselCrudUpdate,
|
||||||
|
};
|
||||||
|
use lib::diesel_crud_trait::DieselCrudCreate;
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
user (email) {
|
||||||
|
#[max_length = 255]
|
||||||
|
email -> Varchar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Queryable, Selectable, Insertable, AsChangeset)]
|
||||||
|
#[diesel(table_name = user)]
|
||||||
|
struct User {
|
||||||
|
email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable)]
|
||||||
|
#[diesel(table_name = user)]
|
||||||
|
struct InsertUser {
|
||||||
|
email: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrud)]
|
||||||
|
#[diesel_crud(table = user, entity = User, pk = String, pk_field = email, create = InsertUser, update = User)]
|
||||||
|
struct TestService {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrudCreate, DieselCrudRead, DieselCrudUpdate, DieselCrudDelete, DieselCrudList)]
|
||||||
|
#[diesel_crud(table = user, entity = User, pk = String, pk_field = email, create = InsertUser, update = User)]
|
||||||
|
struct TestServiceSeparate {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrudCreate)]
|
||||||
|
#[diesel_crud(table = user, entity = User, create = InsertUser)]
|
||||||
|
struct TestServiceCreate {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrudRead)]
|
||||||
|
#[diesel_crud(table = user, entity = User, pk = String)]
|
||||||
|
struct TestServiceRead {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrudUpdate)]
|
||||||
|
#[diesel_crud(table = user, update = User)]
|
||||||
|
struct TestServiceUpdate {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrudDelete)]
|
||||||
|
#[diesel_crud(table = user, pk = String, pk_field = email)]
|
||||||
|
struct TestServiceDelete {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(DieselCrudList)]
|
||||||
|
#[diesel_crud(table = user, entity = User)]
|
||||||
|
struct TestServiceList {
|
||||||
|
pool: Pool<AsyncPgConnection>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_insert_user() {
|
||||||
|
let config = AsyncDieselConnectionManager::<AsyncPgConnection>::new("");
|
||||||
|
let pool = Pool::builder(config).max_size(10).build().unwrap();
|
||||||
|
|
||||||
|
let service = TestServiceCreate { pool };
|
||||||
|
service.create(&InsertUser {
|
||||||
|
email: "test".to_string(),
|
||||||
|
});
|
||||||
|
}
|
112
examples/multipart_file/Cargo.lock
generated
112
examples/multipart_file/Cargo.lock
generated
@ -338,13 +338,14 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "0.8.11"
|
version = "1.0.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
|
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -383,16 +384,6 @@ dependencies = [
|
|||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "num_cpus"
|
|
||||||
version = "1.16.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
|
|
||||||
dependencies = [
|
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.36.1"
|
version = "0.36.1"
|
||||||
@ -563,7 +554,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
|
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -627,25 +618,24 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.38.0"
|
version = "1.39.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a"
|
checksum = "9babc99b9923bfa4804bd74722ff02c0381021eafa4db9949217e3be8e84fff5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"libc",
|
"libc",
|
||||||
"mio",
|
"mio",
|
||||||
"num_cpus",
|
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"socket2",
|
"socket2",
|
||||||
"tokio-macros",
|
"tokio-macros",
|
||||||
"windows-sys 0.48.0",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a"
|
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -811,37 +801,13 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.48.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.48.5",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows-targets 0.52.5",
|
"windows-targets",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-targets"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
|
||||||
dependencies = [
|
|
||||||
"windows_aarch64_gnullvm 0.48.5",
|
|
||||||
"windows_aarch64_msvc 0.48.5",
|
|
||||||
"windows_i686_gnu 0.48.5",
|
|
||||||
"windows_i686_msvc 0.48.5",
|
|
||||||
"windows_x86_64_gnu 0.48.5",
|
|
||||||
"windows_x86_64_gnullvm 0.48.5",
|
|
||||||
"windows_x86_64_msvc 0.48.5",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -850,46 +816,28 @@ version = "0.52.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"windows_aarch64_gnullvm 0.52.5",
|
"windows_aarch64_gnullvm",
|
||||||
"windows_aarch64_msvc 0.52.5",
|
"windows_aarch64_msvc",
|
||||||
"windows_i686_gnu 0.52.5",
|
"windows_i686_gnu",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm",
|
||||||
"windows_i686_msvc 0.52.5",
|
"windows_i686_msvc",
|
||||||
"windows_x86_64_gnu 0.52.5",
|
"windows_x86_64_gnu",
|
||||||
"windows_x86_64_gnullvm 0.52.5",
|
"windows_x86_64_gnullvm",
|
||||||
"windows_x86_64_msvc 0.52.5",
|
"windows_x86_64_msvc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_aarch64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
@ -902,48 +850,24 @@ version = "0.52.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_i686_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnu"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_gnullvm"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows_x86_64_msvc"
|
|
||||||
version = "0.48.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.52.5"
|
version = "0.52.5"
|
||||||
|
@ -6,4 +6,4 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
lib = { path = "../..", features = ["axum"] }
|
lib = { path = "../..", features = ["axum"] }
|
||||||
axum = "0.7.5"
|
axum = "0.7.5"
|
||||||
tokio = { version = "1.38.0", features = ["rt-multi-thread", "macros"] }
|
tokio = { version = "1.39", features = ["rt-multi-thread", "macros"] }
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
|
||||||
#[cfg(all(feature = "derive", feature = "serde"))]
|
#[cfg(all(feature = "derive", feature = "diesel"))]
|
||||||
|
pub extern crate diesel_crud_derive;
|
||||||
|
#[cfg(feature = "diesel")]
|
||||||
|
pub extern crate diesel_crud_trait;
|
||||||
|
#[cfg(all(feature = "derive", feature = "axum", feature = "serde"))]
|
||||||
pub extern crate into_response_derive;
|
pub extern crate into_response_derive;
|
||||||
#[cfg(feature = "read-files")]
|
#[cfg(feature = "read-files")]
|
||||||
pub extern crate read_files;
|
pub extern crate read_files;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user