Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
4970e2570a |
5
.env
5
.env
@ -1 +1,4 @@
|
||||
DATABASE_URL=postgres://postgres:password@localhost/olh
|
||||
APP_ENV=development
|
||||
APP_LOKI_ENDPOINT=http://localhost:3100/loki/api/v1/push
|
||||
APP_LOG_LEVEL=info
|
||||
APP_PORT=3000
|
||||
|
21
.gitignore
vendored
21
.gitignore
vendored
@ -1,22 +1 @@
|
||||
/target
|
||||
/migration/target
|
||||
|
||||
# Added by cargo
|
||||
#
|
||||
# already existing elements were commented out
|
||||
|
||||
#/target
|
||||
|
||||
|
||||
# Added by cargo
|
||||
#
|
||||
# already existing elements were commented out
|
||||
|
||||
#/target
|
||||
|
||||
|
||||
# Added by cargo
|
||||
#
|
||||
# already existing elements were commented out
|
||||
|
||||
#/target
|
||||
|
1409
Cargo.lock
generated
1409
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
14
Cargo.toml
14
Cargo.toml
@ -2,17 +2,11 @@
|
||||
name = "openlayerhub"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
build = "build.rs"
|
||||
|
||||
[build-dependencies]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.95"
|
||||
async-trait = "0.1.86"
|
||||
axum = { version = "0.8.1", features = ["json"] }
|
||||
diesel = { version = "2.2.7", features = ["postgres", "r2d2", "serde_json"] }
|
||||
config = "0.15.7"
|
||||
dotenvy = "0.15.7"
|
||||
r2d2 = "0.8.10"
|
||||
serde = { version = "1.0.217", features = ["derive"] }
|
||||
serde_json = "1.0.138"
|
||||
tokio = { version = "1.43.0", features = ["full"] }
|
||||
tower = "0.5.2"
|
||||
utoipa = { version = "5.3.1", features = ["axum_extras"] }
|
||||
utoipa-swagger-ui = { version = "9.0.0", features = ["axum"] }
|
||||
|
46
build.rs
Normal file
46
build.rs
Normal file
@ -0,0 +1,46 @@
|
||||
use std::env;
|
||||
use std::process::Command;
|
||||
|
||||
fn main() {
|
||||
let is_production = env::var("APP_ENV")
|
||||
.map(|e| e == "production")
|
||||
.unwrap_or(false);
|
||||
|
||||
let version = if is_production {
|
||||
get_latest_tag().unwrap_or_else(|| panic!("Production builds must have a GIT tag."))
|
||||
} else {
|
||||
get_commit_hash().unwrap_or_else(|| env!("CARGO_PKG_VERSION").to_string())
|
||||
};
|
||||
|
||||
println!("cargo:rustc-env=GIT_VERSION={}", version)
|
||||
}
|
||||
|
||||
fn get_commit_hash() -> Option<String> {
|
||||
let output = Command::new("git")
|
||||
.args(&["rev-parse", "--short=8", "HEAD"])
|
||||
.output()
|
||||
.ok()?;
|
||||
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
|
||||
String::from_utf8(output.stdout)
|
||||
.ok()
|
||||
.map(|s| s.trim().to_string())
|
||||
}
|
||||
|
||||
fn get_latest_tag() -> Option<String> {
|
||||
let output = Command::new("git")
|
||||
.args(&["describe", "--tags", "--match", "v*"])
|
||||
.output()
|
||||
.ok()?;
|
||||
|
||||
if !output.status.success() {
|
||||
return None;
|
||||
}
|
||||
|
||||
String::from_utf8(output.stdout)
|
||||
.ok()
|
||||
.map(|s| s.trim().to_string())
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
# For documentation on how to configure this file,
|
||||
# see https://diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/schema.rs"
|
||||
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
||||
|
||||
[migrations_directory]
|
||||
dir = "migrations"
|
516
log
516
log
@ -1,516 +0,0 @@
|
||||
Compiling openlayerhub v0.1.0 (/home/nicolaivds/GIT/OpenLayerHub)
|
||||
error[E0277]: the trait bound `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>` is not satisfied
|
||||
--> src/base/service.rs:60:25
|
||||
|
|
||||
60 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `AsQuery` is not implemented for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>`, which is required by `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>` to implement `LoadQuery<'_, _, _>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
help: consider extending the `where` clause, but there might be an alternative better way to express this requirement
|
||||
|
|
||||
54 | i32: diesel::deserialize::FromSql<diesel::sql_types::Integer, Conn::Backend>, InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: AsQuery
|
||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
error[E0277]: the trait bound `Conn: LoadConnection` is not satisfied
|
||||
--> src/base/service.rs:60:25
|
||||
|
|
||||
60 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `LoadConnection` is not implemented for `Conn`, which is required by `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `PooledConnection<ConnectionManager<Conn>>` to implement `LoadConnection`
|
||||
= note: required for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
50 | Conn: diesel::Connection + R2D2Connection + 'static + diesel::connection::LoadConnection,
|
||||
| ++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: SingleValue` is not satisfied
|
||||
--> src/base/service.rs:60:25
|
||||
|
|
||||
60 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `SingleValue` is not implemented for `<T as HasTable>::Table`, which is required by `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `SqlTypeOrSelectable`
|
||||
= note: required for `T` to implement `FromSqlRow<<T as HasTable>::Table, <Conn as Connection>::Backend>`
|
||||
= note: required for `InsertStatement<<T as HasTable>::Table, <T as diesel::Insertable<<T as HasTable>::Table>>::Values>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
|
||||
error[E0275]: overflow evaluating the requirement `_: Sized`
|
||||
--> src/base/service.rs:67:14
|
||||
|
|
||||
67 | .filter(T::primary_key().eq(id))
|
||||
| ^^^^^^
|
||||
|
|
||||
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`openlayerhub`)
|
||||
= note: required for `<<T as HasTable>::Table as AsQuery>::Query` to implement `FilterDsl<_>`
|
||||
|
||||
error[E0277]: `<<T as HasTable>::Table as AsQuery>::Query` is no valid SQL fragment for the `_` backend
|
||||
--> src/base/service.rs:77:24
|
||||
|
|
||||
77 | .load::<T>(&mut conn)
|
||||
| ---- ^^^^^^^^^ the trait `QueryFragment<_>` is not implemented for `<<T as HasTable>::Table as AsQuery>::Query`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: this usually means that the `_` database system does not support
|
||||
this SQL syntax
|
||||
= help: the following other types implement trait `QueryFragment<DB, SP>`:
|
||||
`&T` implements `QueryFragment<DB>`
|
||||
`()` implements `QueryFragment<DB>`
|
||||
`(T0, T1)` implements `QueryFragment<__DB>`
|
||||
`(T0, T1, T2)` implements `QueryFragment<__DB>`
|
||||
`(T0, T1, T2, T3)` implements `QueryFragment<__DB>`
|
||||
`(T0, T1, T2, T3, T4)` implements `QueryFragment<__DB>`
|
||||
`(T0, T1, T2, T3, T4, T5)` implements `QueryFragment<__DB>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6)` implements `QueryFragment<__DB>`
|
||||
and 278 others
|
||||
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::load`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
||||
|
|
||||
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
|
||||
| ---- required by a bound in this associated function
|
||||
1541 | where
|
||||
1542 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
|
||||
|
||||
error[E0277]: the trait bound `<<T as HasTable>::Table as AsQuery>::Query: QueryId` is not satisfied
|
||||
--> src/base/service.rs:77:24
|
||||
|
|
||||
77 | .load::<T>(&mut conn)
|
||||
| ---- ^^^^^^^^^ the trait `QueryId` is not implemented for `<<T as HasTable>::Table as AsQuery>::Query`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::load`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
||||
|
|
||||
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
|
||||
| ---- required by a bound in this associated function
|
||||
1541 | where
|
||||
1542 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
|
||||
|
||||
error[E0277]: the trait bound `<<T as HasTable>::Table as AsQuery>::SqlType: SingleValue` is not satisfied
|
||||
--> src/base/service.rs:77:24
|
||||
|
|
||||
77 | .load::<T>(&mut conn)
|
||||
| ---- ^^^^^^^^^ the trait `SingleValue` is not implemented for `<<T as HasTable>::Table as AsQuery>::SqlType`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<<T as HasTable>::Table as AsQuery>::SqlType` to implement `load_dsl::private::CompatibleType<T, _>`
|
||||
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::load`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
||||
|
|
||||
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
|
||||
| ---- required by a bound in this associated function
|
||||
1541 | where
|
||||
1542 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
|
||||
|
||||
error[E0277]: the trait bound `T: diesel::Queryable<<<T as HasTable>::Table as AsQuery>::SqlType, _>` is not satisfied
|
||||
--> src/base/service.rs:77:24
|
||||
|
|
||||
77 | .load::<T>(&mut conn)
|
||||
| ---- ^^^^^^^^^ the trait `diesel::Queryable<<<T as HasTable>::Table as AsQuery>::SqlType, _>` is not implemented for `T`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `diesel::Queryable<ST, DB>`:
|
||||
`(T0, T1)` implements `diesel::Queryable<(ST0, ST1), __DB>`
|
||||
`(T0, T1)` implements `diesel::Queryable<Record<(ST0, ST1)>, Pg>`
|
||||
`(T0, T1, T2)` implements `diesel::Queryable<(ST0, ST1, ST2), __DB>`
|
||||
`(T0, T1, T2)` implements `diesel::Queryable<Record<(ST0, ST1, ST2)>, Pg>`
|
||||
`(T0, T1, T2, T3)` implements `diesel::Queryable<(ST0, ST1, ST2, ST3), __DB>`
|
||||
`(T0, T1, T2, T3)` implements `diesel::Queryable<Record<(ST0, ST1, ST2, ST3)>, Pg>`
|
||||
`(T0, T1, T2, T3, T4)` implements `diesel::Queryable<(ST0, ST1, ST2, ST3, ST4), __DB>`
|
||||
`(T0, T1, T2, T3, T4)` implements `diesel::Queryable<Record<(ST0, ST1, ST2, ST3, ST4)>, Pg>`
|
||||
and 116 others
|
||||
= note: required for `T` to implement `FromSqlRow<<<T as HasTable>::Table as AsQuery>::SqlType, _>`
|
||||
= note: required for `<<T as HasTable>::Table as AsQuery>::SqlType` to implement `load_dsl::private::CompatibleType<T, _>`
|
||||
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, _, T>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::load`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
||||
|
|
||||
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
|
||||
| ---- required by a bound in this associated function
|
||||
1541 | where
|
||||
1542 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
|
||||
|
||||
error[E0277]: the trait bound `Conn: LoadConnection` is not satisfied
|
||||
--> src/base/service.rs:77:24
|
||||
|
|
||||
77 | .load::<T>(&mut conn)
|
||||
| ---- ^^^^^^^^^ the trait `LoadConnection` is not implemented for `Conn`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `PooledConnection<ConnectionManager<Conn>>` to implement `LoadConnection`
|
||||
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::load`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
||||
|
|
||||
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
|
||||
| ---- required by a bound in this associated function
|
||||
1541 | where
|
||||
1542 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
50 | Conn: diesel::Connection + R2D2Connection + 'static + diesel::connection::LoadConnection,
|
||||
| ++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `<Conn as Connection>::Backend: QueryMetadata<<<T as HasTable>::Table as AsQuery>::SqlType>` is not satisfied
|
||||
--> src/base/service.rs:77:24
|
||||
|
|
||||
77 | .load::<T>(&mut conn)
|
||||
| ---- ^^^^^^^^^ the trait `HasSqlType<<<T as HasTable>::Table as AsQuery>::SqlType>` is not implemented for `<Conn as Connection>::Backend`, which is required by `<T as HasTable>::Table: LoadQuery<'_, _, T>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<Conn as Connection>::Backend` to implement `QueryMetadata<<<T as HasTable>::Table as AsQuery>::SqlType>`
|
||||
= note: required for `<T as HasTable>::Table` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::load`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1542:15
|
||||
|
|
||||
1540 | fn load<'query, U>(self, conn: &mut Conn) -> QueryResult<Vec<U>>
|
||||
| ---- required by a bound in this associated function
|
||||
1541 | where
|
||||
1542 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::load`
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: IntoUpdateTarget` is not satisfied
|
||||
--> src/base/service.rs:83:24
|
||||
|
|
||||
83 | diesel::update(<T as HasTable>::table())
|
||||
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
|
||||
note: required by a bound in `update`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/functions.rs:80:18
|
||||
|
|
||||
80 | pub fn update<T: IntoUpdateTarget>(source: T) -> UpdateStatement<T::Table, T::WhereClause> {
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `update`
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: HasTable` is not satisfied
|
||||
--> src/base/service.rs:83:9
|
||||
|
|
||||
83 | diesel::update(<T as HasTable>::table())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasTable` is not implemented for `<T as HasTable>::Table`
|
||||
|
||||
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
|
||||
--> src/base/service.rs:84:14
|
||||
|
|
||||
84 | .filter(T::primary_key().eq(id))
|
||||
| ^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `UpdateStatement<_, _>: FilterDsl<_>`
|
||||
|
|
||||
= help: the following other types implement trait `AppearsOnTable<QS>`:
|
||||
`&'a T` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
|
||||
and 131 others
|
||||
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
|
||||
= note: required for `UpdateStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
|
||||
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
|
||||
--> src/base/service.rs:84:21
|
||||
|
|
||||
84 | .filter(T::primary_key().eq(id))
|
||||
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `UpdateStatement<_, _>: FilterDsl<_>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `AppearsOnTable<QS>`:
|
||||
`&'a T` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
|
||||
and 131 others
|
||||
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
|
||||
= note: required for `UpdateStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
|
||||
note: required by a bound in `UpdateStatement::<T, U, V, Ret>::filter`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/update_statement/mod.rs:98:15
|
||||
|
|
||||
96 | pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
|
||||
| ------ required by a bound in this associated function
|
||||
97 | where
|
||||
98 | Self: FilterDsl<Predicate>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `UpdateStatement::<T, U, V, Ret>::filter`
|
||||
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0277]: the trait bound `&T: diesel::AsChangeset` is not satisfied
|
||||
--> src/base/service.rs:85:18
|
||||
|
|
||||
85 | .set(&entity)
|
||||
| --- ^^^^^^^ the trait `diesel::AsChangeset` is not implemented for `&T`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
note: required by a bound in `UpdateStatement::<T, U>::set`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/update_statement/mod.rs:38:12
|
||||
|
|
||||
35 | pub fn set<V>(self, values: V) -> UpdateStatement<T, U, V::Changeset>
|
||||
| --- required by a bound in this associated function
|
||||
...
|
||||
38 | V: changeset::AsChangeset<Target = T>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `UpdateStatement::<T, U>::set`
|
||||
help: consider removing the leading `&`-reference
|
||||
|
|
||||
85 - .set(&entity)
|
||||
85 + .set(entity)
|
||||
|
|
||||
|
||||
error[E0277]: the trait bound `<Conn as Connection>::Backend: DieselReserveSpecialization` is not satisfied
|
||||
--> src/base/service.rs:86:25
|
||||
|
|
||||
86 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `DieselReserveSpecialization` is not implemented for `<Conn as Connection>::Backend`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `UpdateStatement<_, _, _, ReturningClause<_>>` to implement `QueryFragment<<Conn as Connection>::Backend>`
|
||||
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
|
||||
error[E0277]: `ReturningClause<_>` is no valid SQL fragment for the `<Conn as Connection>::Backend` backend
|
||||
--> src/base/service.rs:86:25
|
||||
|
|
||||
86 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `QueryFragment<<Conn as Connection>::Backend, <<Conn as Connection>::Backend as SqlDialect>::ReturningClause>` is not implemented for `ReturningClause<_>`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: this usually means that the `<Conn as Connection>::Backend` database system does not support
|
||||
this SQL syntax
|
||||
= help: the following other types implement trait `QueryFragment<DB, SP>`:
|
||||
`ReturningClause<Expr>` implements `QueryFragment<DB, PgLikeReturningClause>`
|
||||
`ReturningClause<Expr>` implements `QueryFragment<DB>`
|
||||
= note: required for `ReturningClause<_>` to implement `QueryFragment<<Conn as Connection>::Backend>`
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `UpdateStatement<_, _, _, ReturningClause<_>>` to implement `QueryFragment<<Conn as Connection>::Backend>`
|
||||
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
|
||||
error[E0277]: the trait bound `Conn: LoadConnection` is not satisfied
|
||||
--> src/base/service.rs:86:25
|
||||
|
|
||||
86 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `LoadConnection` is not implemented for `Conn`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `PooledConnection<ConnectionManager<Conn>>` to implement `LoadConnection`
|
||||
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, _>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
help: consider further restricting this bound
|
||||
|
|
||||
50 | Conn: diesel::Connection + R2D2Connection + 'static + diesel::connection::LoadConnection,
|
||||
| ++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: SingleValue` is not satisfied
|
||||
--> src/base/service.rs:86:25
|
||||
|
|
||||
86 | .get_result(&mut conn)
|
||||
| ---------- ^^^^^^^^^ the trait `SingleValue` is not implemented for `<T as HasTable>::Table`, which is required by `UpdateStatement<_, _, _>: LoadQuery<'_, _, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `SqlTypeOrSelectable`
|
||||
= note: required for `T` to implement `FromSqlRow<<T as HasTable>::Table, <Conn as Connection>::Backend>`
|
||||
= note: required for `UpdateStatement<_, _, _>` to implement `LoadQuery<'_, PooledConnection<ConnectionManager<Conn>>, T>`
|
||||
note: required by a bound in `get_result`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1722:15
|
||||
|
|
||||
1720 | fn get_result<'query, U>(self, conn: &mut Conn) -> QueryResult<U>
|
||||
| ---------- required by a bound in this associated function
|
||||
1721 | where
|
||||
1722 | Self: LoadQuery<'query, Conn, U>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::get_result`
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: diesel::Identifiable` is not satisfied
|
||||
--> src/base/service.rs:83:9
|
||||
|
|
||||
83 | diesel::update(<T as HasTable>::table())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: IntoUpdateTarget` is not satisfied
|
||||
--> src/base/service.rs:92:24
|
||||
|
|
||||
92 | diesel::delete(<T as HasTable>::table())
|
||||
| -------------- ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
|
||||
note: required by a bound in `delete`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/functions.rs:132:18
|
||||
|
|
||||
132 | pub fn delete<T: IntoUpdateTarget>(source: T) -> DeleteStatement<T::Table, T::WhereClause> {
|
||||
| ^^^^^^^^^^^^^^^^ required by this bound in `delete`
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: HasTable` is not satisfied
|
||||
--> src/base/service.rs:92:9
|
||||
|
|
||||
92 | diesel::delete(<T as HasTable>::table())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasTable` is not implemented for `<T as HasTable>::Table`
|
||||
|
||||
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
|
||||
--> src/base/service.rs:93:14
|
||||
|
|
||||
93 | .filter(T::primary_key().eq(id))
|
||||
| ^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `DeleteStatement<_, _>: FilterDsl<_>`
|
||||
|
|
||||
= help: the following other types implement trait `AppearsOnTable<QS>`:
|
||||
`&'a T` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
|
||||
and 131 others
|
||||
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
|
||||
= note: required for `DeleteStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
|
||||
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0277]: the trait bound `<T as Model>::PrimaryKey: AppearsOnTable<_>` is not satisfied
|
||||
--> src/base/service.rs:93:21
|
||||
|
|
||||
93 | .filter(T::primary_key().eq(id))
|
||||
| ------ ^^^^^^^^^^^^^^^^^^^^^^^ the trait `AppearsOnTable<_>` is not implemented for `<T as Model>::PrimaryKey`, which is required by `DeleteStatement<_, _>: FilterDsl<_>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= help: the following other types implement trait `AppearsOnTable<QS>`:
|
||||
`&'a T` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6)` implements `AppearsOnTable<QS>`
|
||||
`(T0, T1, T2, T3, T4, T5, T6, T7)` implements `AppearsOnTable<QS>`
|
||||
and 131 others
|
||||
= note: required for `diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>` to implement `AppearsOnTable<_>`
|
||||
= note: 1 redundant requirement hidden
|
||||
= note: required for `Grouped<Eq<<T as Model>::PrimaryKey, Bound<Integer, i32>>>` to implement `AppearsOnTable<_>`
|
||||
= note: required for `DeleteStatement<_, _>` to implement `FilterDsl<diesel::expression::grouped::Grouped<diesel::expression::operators::Eq<<T as Model>::PrimaryKey, diesel::expression::bound::Bound<Integer, i32>>>>`
|
||||
note: required by a bound in `DeleteStatement::<T, U>::filter`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_builder/delete_statement/mod.rs:113:15
|
||||
|
|
||||
111 | pub fn filter<Predicate>(self, predicate: Predicate) -> Filter<Self, Predicate>
|
||||
| ------ required by a bound in this associated function
|
||||
112 | where
|
||||
113 | Self: FilterDsl<Predicate>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^ required by this bound in `DeleteStatement::<T, U>::filter`
|
||||
= note: the full name for the type has been written to '/home/nicolaivds/GIT/OpenLayerHub/target/debug/deps/openlayerhub-1f7d339452a03941.long-type-9065444121950834043.txt'
|
||||
= note: consider using `--verbose` to print the full type name to the console
|
||||
|
||||
error[E0277]: the trait bound `<Conn as Connection>::Backend: DieselReserveSpecialization` is not satisfied
|
||||
--> src/base/service.rs:94:22
|
||||
|
|
||||
94 | .execute(&mut conn)
|
||||
| ------- ^^^^^^^^^ the trait `DieselReserveSpecialization` is not implemented for `<Conn as Connection>::Backend`, which is required by `DeleteStatement<_, _>: ExecuteDsl<_, _>`
|
||||
| |
|
||||
| required by a bound introduced by this call
|
||||
|
|
||||
= note: required for `DeleteStatement<_, _>` to implement `QueryFragment<<Conn as Connection>::Backend>`
|
||||
= note: required for `DeleteStatement<_, _>` to implement `ExecuteDsl<PooledConnection<ConnectionManager<Conn>>, <Conn as Connection>::Backend>`
|
||||
note: required by a bound in `diesel::RunQueryDsl::execute`
|
||||
--> /home/nicolaivds/.cargo/registry/src/index.crates.io-6f17d22bba15001f/diesel-2.2.7/src/query_dsl/mod.rs:1431:15
|
||||
|
|
||||
1428 | fn execute(self, conn: &mut Conn) -> QueryResult<usize>
|
||||
| ------- required by a bound in this associated function
|
||||
...
|
||||
1431 | Self: methods::ExecuteDsl<Conn>,
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `RunQueryDsl::execute`
|
||||
|
||||
error[E0277]: the trait bound `<T as HasTable>::Table: diesel::Identifiable` is not satisfied
|
||||
--> src/base/service.rs:92:9
|
||||
|
|
||||
92 | diesel::delete(<T as HasTable>::table())
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `diesel::Identifiable` is not implemented for `<T as HasTable>::Table`, which is required by `<T as HasTable>::Table: IntoUpdateTarget`
|
||||
|
|
||||
= note: required for `<T as HasTable>::Table` to implement `IntoUpdateTarget`
|
||||
|
||||
Some errors have detailed explanations: E0275, E0277.
|
||||
For more information about an error, try `rustc --explain E0275`.
|
||||
error: could not compile `openlayerhub` (bin "openlayerhub") due to 26 previous errors
|
@ -1,6 +0,0 @@
|
||||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
DROP FUNCTION IF EXISTS diesel_manage_updated_at(_tbl regclass);
|
||||
DROP FUNCTION IF EXISTS diesel_set_updated_at();
|
@ -1,36 +0,0 @@
|
||||
-- This file was automatically created by Diesel to setup helper functions
|
||||
-- and other internal bookkeeping. This file is safe to edit, any future
|
||||
-- changes will be added to existing projects as new migrations.
|
||||
|
||||
|
||||
|
||||
|
||||
-- Sets up a trigger for the given table to automatically set a column called
|
||||
-- `updated_at` whenever the row is modified (unless `updated_at` was included
|
||||
-- in the modified columns)
|
||||
--
|
||||
-- # Example
|
||||
--
|
||||
-- ```sql
|
||||
-- CREATE TABLE users (id SERIAL PRIMARY KEY, updated_at TIMESTAMP NOT NULL DEFAULT NOW());
|
||||
--
|
||||
-- SELECT diesel_manage_updated_at('users');
|
||||
-- ```
|
||||
CREATE OR REPLACE FUNCTION diesel_manage_updated_at(_tbl regclass) RETURNS VOID AS $$
|
||||
BEGIN
|
||||
EXECUTE format('CREATE TRIGGER set_updated_at BEFORE UPDATE ON %s
|
||||
FOR EACH ROW EXECUTE PROCEDURE diesel_set_updated_at()', _tbl);
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE OR REPLACE FUNCTION diesel_set_updated_at() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
IF (
|
||||
NEW IS DISTINCT FROM OLD AND
|
||||
NEW.updated_at IS NOT DISTINCT FROM OLD.updated_at
|
||||
) THEN
|
||||
NEW.updated_at := current_timestamp;
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
@ -1 +0,0 @@
|
||||
DROP TABLE users;
|
@ -1,5 +0,0 @@
|
||||
CREATE TABLE users (
|
||||
id SERIAL PRIMARY KEY,
|
||||
name VARCHAR NOT NULL,
|
||||
email VARCHAR NOT NULL UNIQUE
|
||||
);
|
@ -1,78 +0,0 @@
|
||||
use crate::base::{entity::BaseEntity, i_service::IBaseService};
|
||||
use anyhow::Result;
|
||||
use axum::{extract::{Path, State}, http::StatusCode, response::IntoResponse, routing::get, Json, Router};
|
||||
use diesel::Identifiable;
|
||||
use serde::Serialize;
|
||||
use std::{marker::PhantomData, ops::Deref, sync::Arc};
|
||||
|
||||
pub struct BaseController<T, S>
|
||||
where
|
||||
T: BaseEntity + Identifiable<Id = i32> + Serialize + Send + Sync + 'static,
|
||||
S: IBaseService<T> + Send + Sync + 'static,
|
||||
{
|
||||
service: S,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T, S> BaseController<T, S>
|
||||
where
|
||||
T: BaseEntity + Identifiable<Id = i32> + Serialize + Send + Sync + 'static,
|
||||
S: IBaseService<T> + Send + Sync + 'static,
|
||||
{
|
||||
pub fn new(service: S) -> Self {
|
||||
Self {
|
||||
service,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_all(&self) -> Result<impl IntoResponse, String> {
|
||||
let entities = self
|
||||
.service
|
||||
.get_all()
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
Ok((StatusCode::OK, Json(entities)))
|
||||
}
|
||||
|
||||
pub async fn get_by_id(&self, id: i32) -> Result<impl IntoResponse, String> {
|
||||
let entity = self
|
||||
.service
|
||||
.get_by_id(id)
|
||||
.await
|
||||
.map_err(|err| err.to_string())?;
|
||||
|
||||
match entity {
|
||||
Some(entity) => Ok((StatusCode::OK, Json(entity))),
|
||||
None => Err(format!("Entity with id {} not found.", id))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn default_routes<C>(controller: Arc<C>, base_path: &str) -> Router
|
||||
where
|
||||
C: Deref<Target = Self> + Send + Sync + 'static,
|
||||
{
|
||||
Router::new()
|
||||
.route(
|
||||
&format!("{}", base_path),
|
||||
get(|State(controller): State<Arc<C>>| async move {
|
||||
controller
|
||||
.get_all()
|
||||
.await
|
||||
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, Json(err)))
|
||||
}),
|
||||
)
|
||||
|
||||
.route(
|
||||
// Add route for getting by ID (e.g., /:id)
|
||||
&format!("{}/{{id}}", base_path),
|
||||
get(|State(controller): State<Arc<C>>, Path(id): Path<i32>| async move {
|
||||
controller
|
||||
.get_by_id(id)
|
||||
.await
|
||||
.map_err(|err| (StatusCode::NOT_FOUND, Json(err)))
|
||||
}),
|
||||
)
|
||||
.with_state(controller)
|
||||
}
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub trait BaseEntity {
|
||||
fn id(&self) -> i32;
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||
pub struct Entity {
|
||||
pub id: i32,
|
||||
}
|
||||
|
||||
impl BaseEntity for Entity {
|
||||
fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
}
|
@ -1,11 +0,0 @@
|
||||
use anyhow::{Error, Result};
|
||||
use async_trait::async_trait;
|
||||
|
||||
#[async_trait]
|
||||
pub trait IBaseService<T> {
|
||||
async fn get_all(&self) -> Result<Vec<T>, Error>;
|
||||
async fn get_by_id(&self, id: i32) -> Result<Option<T>, Error>;
|
||||
async fn update(&self, entity: T) -> Result<T, Error>;
|
||||
//async fn create(&self, entity: T) -> Result<i32, Error>;
|
||||
async fn delete(&self, id: i32) -> Result<bool, Error>;
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
pub mod i_service;
|
||||
pub mod service;
|
||||
pub mod controller;
|
||||
pub mod entity;
|
@ -1,89 +0,0 @@
|
||||
use std::marker::PhantomData;
|
||||
use anyhow::Error;
|
||||
use async_trait::async_trait;
|
||||
use diesel::prelude::*;
|
||||
use diesel::associations::HasTable;
|
||||
use diesel::query_dsl::methods::{FindDsl, LoadQuery};
|
||||
|
||||
use crate::config::db::{get_connection, DbPool};
|
||||
use super::i_service::IBaseService;
|
||||
|
||||
pub struct BaseService<T, U>
|
||||
where
|
||||
T: Identifiable<Id = i32> + Queryable<U::SqlType, diesel::pg::Pg> + Send + Sync + 'static,
|
||||
U: Table + HasTable<Table = U> + LoadQuery<'static, PgConnection, T> + Send + Sync + 'static,
|
||||
{
|
||||
pool: DbPool,
|
||||
_marker: PhantomData<(T, U)>,
|
||||
}
|
||||
|
||||
impl<T, U> BaseService<T, U>
|
||||
where
|
||||
T: Identifiable<Id = i32> + Queryable<U::SqlType, diesel::pg::Pg> + Send + Sync + 'static,
|
||||
U: Table
|
||||
+ HasTable<Table = U>
|
||||
+ LoadQuery<'static, PgConnection, T>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
{
|
||||
pub fn new(pool: DbPool) -> Self {
|
||||
Self {
|
||||
pool,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, U> IBaseService<T> for BaseService<T, U>
|
||||
where
|
||||
T: Identifiable<Id = i32> + Queryable<U::SqlType, diesel::pg::Pg> + Send + Sync + 'static,
|
||||
U: Table
|
||||
+ HasTable<Table = U>
|
||||
+ LoadQuery<'static, PgConnection, T>
|
||||
+ FindDsl<i32>
|
||||
+ Send
|
||||
+ Sync
|
||||
+ 'static,
|
||||
<U as FindDsl<i32>>::Output: LoadQuery<'static, PgConnection, T>,
|
||||
{
|
||||
async fn get_all(&self) -> Result<Vec<T>, Error> {
|
||||
let pool = self.pool.clone();
|
||||
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
let mut conn = get_connection(&pool).expect("Failed to get DB connection");
|
||||
U::table().load::<T>(&mut conn)
|
||||
})
|
||||
.await??;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
async fn get_by_id(&self, id: i32) -> Result<Option<T>, Error> {
|
||||
let pool = self.pool.clone();
|
||||
|
||||
let result = tokio::task::spawn_blocking(move || {
|
||||
let mut conn = get_connection(&pool).expect("Failed to get DB connection");
|
||||
U::table()
|
||||
.find(id)
|
||||
.get_result::<T>(&mut conn)
|
||||
.optional()
|
||||
})
|
||||
.await??;
|
||||
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
async fn update(&self, entity: T) -> Result<T, Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// async fn create(&self, entity: T) -> Result<T, Error> {
|
||||
// todo!()
|
||||
// }
|
||||
|
||||
async fn delete(&self, id: i32) -> Result<bool, Error> {
|
||||
todo!()
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
use diesel::pg::PgConnection;
|
||||
use diesel::r2d2::{self, ConnectionManager, Pool, PoolError};
|
||||
|
||||
use std::env;
|
||||
|
||||
pub type DbPool = Pool<ConnectionManager<PgConnection>>;
|
||||
|
||||
pub fn establish_connection_pool() -> Result<DbPool, PoolError> {
|
||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
|
||||
let manager = ConnectionManager::<PgConnection>::new(database_url);
|
||||
Pool::builder().build(manager)
|
||||
}
|
||||
|
||||
pub fn get_connection(
|
||||
pool: &DbPool,
|
||||
) -> Result<r2d2::PooledConnection<ConnectionManager<PgConnection>>, PoolError> {
|
||||
pool.get()
|
||||
}
|
||||
|
||||
pub fn init_db() -> DbPool {
|
||||
establish_connection_pool().expect("Failed to create connection pool")
|
||||
}
|
@ -1 +1 @@
|
||||
pub mod db;
|
||||
pub mod parameter;
|
||||
|
63
src/config/parameter.rs
Normal file
63
src/config/parameter.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use config::{Config, ConfigError, Environment, File};
|
||||
use dotenvy::dotenv;
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
|
||||
#[derive(Debug, Deserialize, Clone)]
|
||||
pub struct AppConfig {
|
||||
pub loki_endpoint: String,
|
||||
pub service_name: String,
|
||||
pub service_version: String,
|
||||
pub log_level: String,
|
||||
pub port: u16,
|
||||
pub environment: String,
|
||||
}
|
||||
|
||||
impl AppConfig {
|
||||
pub fn new() -> Result<Self, ConfigError> {
|
||||
let _ = dotenv().ok();
|
||||
|
||||
let environment = env::var("APP_ENV").unwrap_or_else(|_| "development".into());
|
||||
|
||||
let config = Config::builder()
|
||||
// Start with default values
|
||||
.set_default("environment", &*environment)?
|
||||
.set_default("service_name", "OpenLayersHub")?
|
||||
.set_default("service_version", env!("GIT_VERSION"))?
|
||||
.set_default("log_level", "info")?
|
||||
.set_default("port", 3000)?
|
||||
// Add environment-specific config file
|
||||
.add_source(File::with_name(&format!("config/{}", environment)).required(false))
|
||||
.add_source(File::with_name(".env").required(false))
|
||||
.add_source(
|
||||
Environment::with_prefix("APP")
|
||||
.prefix_separator("_")
|
||||
.separator("__"),
|
||||
)
|
||||
.build()?;
|
||||
|
||||
config.try_deserialize()
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<(), Vec<String>> {
|
||||
let mut errors = Vec::new();
|
||||
|
||||
if self.loki_endpoint.is_empty() {
|
||||
errors.push("Loki endpoint must be set".to_string());
|
||||
}
|
||||
|
||||
// Validate environment value
|
||||
if !["development", "staging", "production"].contains(&self.environment.as_str()) {
|
||||
errors.push(format!(
|
||||
"Invalid environment '{}'. Must be one of: development, staging, production",
|
||||
self.environment
|
||||
));
|
||||
}
|
||||
|
||||
if errors.is_empty() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(errors)
|
||||
}
|
||||
}
|
||||
}
|
65
src/main.rs
65
src/main.rs
@ -1,51 +1,24 @@
|
||||
use std::sync::Arc;
|
||||
use crate::config::parameter::AppConfig;
|
||||
|
||||
use crate::routes::user::controller::UserController;
|
||||
use crate::routes::user::model::{User, UserResponse};
|
||||
use crate::routes::user::service::UserService;
|
||||
use axum::http::StatusCode;
|
||||
use axum::routing::get;
|
||||
use axum::{serve, Router};
|
||||
use config::db::init_db;
|
||||
use dotenvy::dotenv;
|
||||
use tokio::net::TcpListener;
|
||||
use utoipa::OpenApi;
|
||||
use utoipa_swagger_ui::SwaggerUi;
|
||||
|
||||
mod base;
|
||||
mod config;
|
||||
mod routes;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
dotenv().ok();
|
||||
let pool = init_db();
|
||||
fn main() {
|
||||
let config = AppConfig::new()
|
||||
.map_err(|e| {
|
||||
eprintln!("Configuration error: {}", e);
|
||||
std::process::exit(1);
|
||||
})
|
||||
.and_then(|cfg| {
|
||||
cfg.validate().map_err(|errors| {
|
||||
eprintln!(
|
||||
"Configuration validation errors:\n\t{}",
|
||||
errors.join("\n\t")
|
||||
);
|
||||
std::process::exit(1);
|
||||
})?;
|
||||
Ok(cfg)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let hc_router = Router::new().route("/", get(health_check));
|
||||
|
||||
let user_service = UserService::new(pool);
|
||||
let user_controller = Arc::new(UserController::new(user_service));
|
||||
|
||||
let app = Router::new()
|
||||
.merge(UserController::routes(user_controller.clone()))
|
||||
.merge(SwaggerUi::new("/swagger-ui").url("/api-docs/openapi.json", ApiDoc::openapi()))
|
||||
.nest("/hc", hc_router);
|
||||
|
||||
let listener = TcpListener::bind("0.0.0.0:3000").await.unwrap();
|
||||
serve(listener, app).await.unwrap();
|
||||
|
||||
async fn health_check() -> StatusCode {
|
||||
StatusCode::OK
|
||||
}
|
||||
|
||||
#[derive(OpenApi)]
|
||||
#[openapi(
|
||||
components(
|
||||
schemas(User, UserResponse)
|
||||
),
|
||||
tags(
|
||||
(name = "users", description = "User management endpoints")
|
||||
)
|
||||
)]
|
||||
struct ApiDoc;
|
||||
println!("Hello, world! {}", config.service_version);
|
||||
}
|
||||
|
@ -1 +0,0 @@
|
||||
pub mod user;
|
@ -1,44 +0,0 @@
|
||||
use std::ops::Deref;
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::base::controller::BaseController;
|
||||
use axum::Router;
|
||||
|
||||
use super::model::User;
|
||||
use super::service::UserService;
|
||||
|
||||
pub struct UserController {
|
||||
base_controller: BaseController<User, UserService>,
|
||||
}
|
||||
|
||||
impl Deref for UserController {
|
||||
type Target = BaseController<User, UserService>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.base_controller
|
||||
}
|
||||
}
|
||||
|
||||
impl UserController {
|
||||
pub fn new(service: UserService) -> Self {
|
||||
Self {
|
||||
base_controller: BaseController::new(service),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn routes(controller: Arc<Self>) -> Router {
|
||||
BaseController::default_routes(controller, "/users")
|
||||
}
|
||||
|
||||
/*
|
||||
async fn get_users(
|
||||
State(controller): State<Arc<UserController>>,
|
||||
) -> Result<impl IntoResponse, (StatusCode, Json<String>)> {
|
||||
controller
|
||||
.base_controller
|
||||
.get_all()
|
||||
.await
|
||||
.map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, Json(err)))
|
||||
}
|
||||
*/
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
pub mod model;
|
||||
pub mod schema;
|
||||
pub mod service;
|
||||
pub mod controller;
|
@ -1,35 +0,0 @@
|
||||
use super::schema::users;
|
||||
use crate::base::entity::BaseEntity;
|
||||
use diesel::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use utoipa::ToSchema;
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, ToSchema)]
|
||||
#[diesel(table_name = users, primary_key(id))]
|
||||
pub struct User {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, ToSchema)]
|
||||
pub struct UserResponse {
|
||||
pub id: i32,
|
||||
pub name: String,
|
||||
pub email: String,
|
||||
}
|
||||
|
||||
impl BaseEntity for User {
|
||||
fn id(&self) -> i32 {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
||||
impl Identifiable for User {
|
||||
type Id = i32;
|
||||
|
||||
fn id(self) -> Self::Id {
|
||||
self.id
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +0,0 @@
|
||||
use diesel::table;
|
||||
|
||||
table! {
|
||||
users (id) {
|
||||
id -> Integer,
|
||||
name -> Varchar,
|
||||
email -> Varchar,
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
use crate::base::service::BaseService;
|
||||
use super::model::User;
|
||||
use super::schema::users;
|
||||
|
||||
pub type UserService = BaseService<User, users::table>;
|
@ -1,9 +0,0 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
users (id) {
|
||||
id -> Int4,
|
||||
name -> Varchar,
|
||||
email -> Varchar,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user