Compare commits
2 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
de3882c8b1 | ||
61da72936e |
@ -12,10 +12,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: actions-rust-lang/setup-rust-toolchain@v1
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --verbose
|
run: cargo build --verbose
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test --verbose --all-features --workspace
|
run: cargo test --verbose --all-features --workspace
|
395
Cargo.lock
generated
395
Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 4
|
version = 3
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
@ -66,13 +66,13 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum"
|
name = "axum"
|
||||||
version = "0.8.1"
|
version = "0.7.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8"
|
checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"axum-core",
|
"axum-core",
|
||||||
"bytes",
|
"bytes",
|
||||||
"form_urlencoded",
|
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
@ -91,9 +91,9 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_path_to_error",
|
"serde_path_to_error",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper 1.0.1",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower 0.5.2",
|
"tower 0.4.13",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -101,10 +101,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "axum-core"
|
name = "axum-core"
|
||||||
version = "0.5.0"
|
version = "0.4.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733"
|
checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"http",
|
"http",
|
||||||
@ -113,7 +114,7 @@ dependencies = [
|
|||||||
"mime",
|
"mime",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"rustversion",
|
"rustversion",
|
||||||
"sync_wrapper",
|
"sync_wrapper 0.1.2",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
"tracing",
|
"tracing",
|
||||||
@ -198,7 +199,7 @@ dependencies = [
|
|||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_repr",
|
"serde_repr",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"thiserror 1.0.63",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@ -428,18 +429,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more"
|
name = "derive_more"
|
||||||
version = "2.0.1"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
|
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_more-impl",
|
"derive_more-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_more-impl"
|
name = "derive_more-impl"
|
||||||
version = "2.0.1"
|
version = "1.0.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
|
checksum = "cb7330aeadfbe296029522e6c40f315320aba36fc43a5b3632f3795348f3bd22"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -488,9 +489,34 @@ dependencies = [
|
|||||||
name = "diesel-crud-trait"
|
name = "diesel-crud-trait"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"deadpool-diesel",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel-async",
|
"diesel-async",
|
||||||
"thiserror 2.0.12",
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_async_migrations"
|
||||||
|
version = "0.14.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b92dd60c54ac548b3a001a040e92abdca9b55c68136c8a641ef776dfeb133a52"
|
||||||
|
dependencies = [
|
||||||
|
"diesel",
|
||||||
|
"diesel-async",
|
||||||
|
"diesel_async_migrations_macros",
|
||||||
|
"scoped-futures",
|
||||||
|
"tracing",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel_async_migrations_macros"
|
||||||
|
version = "0.12.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05de210f31e6ac18162501b03c37f839af9f9fd6dd6de2bb4031ae6691c47679"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -506,17 +532,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "diesel_migrations"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "8a73ce704bad4231f001bff3314d91dce4aba0770cee8b233991859abc15c1f6"
|
|
||||||
dependencies = [
|
|
||||||
"diesel",
|
|
||||||
"migrations_internals",
|
|
||||||
"migrations_macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diesel_table_macro_syntax"
|
name = "diesel_table_macro_syntax"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
@ -537,6 +552,27 @@ dependencies = [
|
|||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "5.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
|
||||||
|
dependencies = [
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.4.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"option-ext",
|
||||||
|
"redox_users",
|
||||||
|
"windows-sys 0.48.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "docker_credential"
|
name = "docker_credential"
|
||||||
version = "1.3.1"
|
version = "1.3.1"
|
||||||
@ -583,45 +619,12 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "errno"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "etcetera"
|
|
||||||
version = "0.8.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"home",
|
|
||||||
"windows-sys 0.48.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fallible-iterator"
|
name = "fallible-iterator"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "filetime"
|
|
||||||
version = "0.2.25"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
|
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
"libc",
|
|
||||||
"libredox",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
@ -1038,7 +1041,7 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lib"
|
name = "lib"
|
||||||
version = "2.0.0"
|
version = "1.4.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"axum",
|
"axum",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -1048,18 +1051,15 @@ dependencies = [
|
|||||||
"diesel-async",
|
"diesel-async",
|
||||||
"diesel-crud-derive",
|
"diesel-crud-derive",
|
||||||
"diesel-crud-trait",
|
"diesel-crud-trait",
|
||||||
"diesel_migrations",
|
|
||||||
"into-response-derive",
|
"into-response-derive",
|
||||||
"mime",
|
"mime",
|
||||||
"nom",
|
"nom",
|
||||||
"read-files",
|
"read-files",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"thiserror",
|
||||||
"testcontainers-modules",
|
|
||||||
"thiserror 2.0.12",
|
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower 0.5.2",
|
"tower 0.5.0",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@ -1067,9 +1067,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.170"
|
version = "0.2.158"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "875b3680cb2f8f71bdcf9a30f38d48282f5d3c95cbf9b3fa57269bb5d5c06828"
|
checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
@ -1079,15 +1079,8 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall 0.5.3",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "linux-raw-sys"
|
|
||||||
version = "0.4.15"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
@ -1106,9 +1099,9 @@ checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "matchit"
|
name = "matchit"
|
||||||
version = "0.8.4"
|
version = "0.7.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3"
|
checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "md-5"
|
name = "md-5"
|
||||||
@ -1126,33 +1119,18 @@ version = "2.7.4"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "migrations_internals"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fd01039851e82f8799046eabbb354056283fb265c8ec0996af940f4e85a380ff"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"toml",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "migrations_macros"
|
|
||||||
version = "2.2.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "ffb161cc72176cb37aa47f1fc520d3ef02263d67d661f44f05d05a079e1237fd"
|
|
||||||
dependencies = [
|
|
||||||
"migrations_internals",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mime"
|
name = "mime"
|
||||||
version = "0.3.17"
|
version = "0.3.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "minimal-lexical"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "miniz_oxide"
|
name = "miniz_oxide"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
@ -1193,11 +1171,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "8.0.0"
|
version = "7.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
|
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1256,6 +1235,12 @@ version = "0.1.5"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "option-ext"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "overload"
|
name = "overload"
|
||||||
version = "0.1.1"
|
version = "0.1.1"
|
||||||
@ -1426,7 +1411,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"toml_edit 0.19.15",
|
"toml_edit",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1486,15 +1471,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "redox_syscall"
|
|
||||||
version = "0.3.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -1514,10 +1490,21 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "redox_users"
|
||||||
version = "1.11.1"
|
version = "0.4.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
|
checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom",
|
||||||
|
"libredox",
|
||||||
|
"thiserror",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "regex"
|
||||||
|
version = "1.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -1527,9 +1514,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-automata"
|
name = "regex-automata"
|
||||||
version = "0.4.9"
|
version = "0.4.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aho-corasick",
|
"aho-corasick",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -1538,9 +1525,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex-syntax"
|
name = "regex-syntax"
|
||||||
version = "0.8.5"
|
version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
|
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ring"
|
name = "ring"
|
||||||
@ -1563,19 +1550,6 @@ version = "0.1.24"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "rustix"
|
|
||||||
version = "0.38.44"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 2.6.0",
|
|
||||||
"errno",
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys",
|
|
||||||
"windows-sys 0.59.0",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.12"
|
version = "0.23.12"
|
||||||
@ -1743,15 +1717,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_spanned"
|
|
||||||
version = "0.6.8"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_urlencoded"
|
name = "serde_urlencoded"
|
||||||
version = "0.7.1"
|
version = "0.7.1"
|
||||||
@ -1911,15 +1876,21 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.87"
|
version = "2.0.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d"
|
checksum = "578e081a14e0cefc3279b0472138c513f37b41a08d5a3cca9b6e4e8ceb6cd525"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sync_wrapper"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sync_wrapper"
|
name = "sync_wrapper"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@ -1928,17 +1899,17 @@ checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "testcontainers"
|
name = "testcontainers"
|
||||||
version = "0.23.1"
|
version = "0.21.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5f40cc2bd72e17f328faf8ca7687fe337e61bccd8acf9674fa78dd3792b045e1"
|
checksum = "5f7d80fe0008971413157e67062150cbf508b92f0eb525b9f49de1aec4267f24"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
"async-trait",
|
||||||
"bollard",
|
"bollard",
|
||||||
"bollard-stubs",
|
"bollard-stubs",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
"dirs",
|
||||||
"docker_credential",
|
"docker_credential",
|
||||||
"either",
|
"either",
|
||||||
"etcetera",
|
|
||||||
"futures",
|
"futures",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
@ -1947,19 +1918,18 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_with",
|
"serde_with",
|
||||||
"thiserror 1.0.63",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-tar",
|
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "testcontainers-modules"
|
name = "testcontainers-modules"
|
||||||
version = "0.11.6"
|
version = "0.9.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4d43ed4e8f58424c3a2c6c56dbea6643c3c23e8666a34df13c54f0a184e6c707"
|
checksum = "868e8e818fe37b8ed4c21ac72185206b48e8767b5ad3836d7ec0e5c9386e19a2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"testcontainers",
|
"testcontainers",
|
||||||
]
|
]
|
||||||
@ -1968,9 +1938,10 @@ dependencies = [
|
|||||||
name = "tests"
|
name = "tests"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"derive_more",
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel-async",
|
"diesel-async",
|
||||||
"diesel_migrations",
|
"diesel_async_migrations",
|
||||||
"lib",
|
"lib",
|
||||||
"testcontainers-modules",
|
"testcontainers-modules",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -1982,16 +1953,7 @@ version = "1.0.63"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
|
checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl 1.0.63",
|
"thiserror-impl",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl 2.0.12",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2005,17 +1967,6 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thread_local"
|
name = "thread_local"
|
||||||
version = "1.1.8"
|
version = "1.1.8"
|
||||||
@ -2147,21 +2098,6 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tokio-tar"
|
|
||||||
version = "0.3.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d5714c010ca3e5c27114c1cdeb9d14641ace49874aa5626d7149e47aedace75"
|
|
||||||
dependencies = [
|
|
||||||
"filetime",
|
|
||||||
"futures-core",
|
|
||||||
"libc",
|
|
||||||
"redox_syscall 0.3.5",
|
|
||||||
"tokio",
|
|
||||||
"tokio-stream",
|
|
||||||
"xattr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.11"
|
version = "0.7.11"
|
||||||
@ -2175,26 +2111,11 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml"
|
|
||||||
version = "0.8.20"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"toml_edit 0.22.24",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_datetime"
|
name = "toml_datetime"
|
||||||
version = "0.6.8"
|
version = "0.6.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml_edit"
|
name = "toml_edit"
|
||||||
@ -2204,20 +2125,7 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"indexmap 2.4.0",
|
"indexmap 2.4.0",
|
||||||
"toml_datetime",
|
"toml_datetime",
|
||||||
"winnow 0.5.40",
|
"winnow",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_edit"
|
|
||||||
version = "0.22.24"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
|
|
||||||
dependencies = [
|
|
||||||
"indexmap 2.4.0",
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"winnow 0.7.3",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -2233,34 +2141,30 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "tower"
|
|
||||||
version = "0.5.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9"
|
|
||||||
dependencies = [
|
|
||||||
"futures-core",
|
|
||||||
"futures-util",
|
|
||||||
"pin-project-lite",
|
|
||||||
"sync_wrapper",
|
|
||||||
"tokio",
|
|
||||||
"tower-layer",
|
|
||||||
"tower-service",
|
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tower-http"
|
name = "tower"
|
||||||
version = "0.6.2"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "403fa3b783d4b626a8ad51d766ab03cb6d2dbfc46b1c5d4448395e6628dc9697"
|
checksum = "36b837f86b25d7c0d7988f00a54e74739be6477f2aac6201b8f429a7569991b7"
|
||||||
|
dependencies = [
|
||||||
|
"tower-layer",
|
||||||
|
"tower-service",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tower-http"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"bytes",
|
"bytes",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
|
"http-body-util",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"tower-layer",
|
"tower-layer",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@ -2558,15 +2462,6 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "windows-sys"
|
|
||||||
version = "0.59.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
|
||||||
dependencies = [
|
|
||||||
"windows-targets 0.52.6",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-targets"
|
name = "windows-targets"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -2697,26 +2592,6 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "winnow"
|
|
||||||
version = "0.7.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "0e7f4ea97f6f78012141bcdb6a216b2609f0979ada50b20ca5b52dde2eac2bb1"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "xattr"
|
|
||||||
version = "1.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e105d177a3871454f754b33bb0ee637ecaaac997446375fd3e5d43a2ed00c909"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
"linux-raw-sys",
|
|
||||||
"rustix",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "zerocopy"
|
||||||
version = "0.7.35"
|
version = "0.7.35"
|
||||||
|
33
Cargo.toml
33
Cargo.toml
@ -3,14 +3,14 @@ members = ["crates/*"]
|
|||||||
exclude = ["examples"]
|
exclude = ["examples"]
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
edition = "2024"
|
edition = "2021"
|
||||||
rust-version = "1.85"
|
rust-version = "1.80.1"
|
||||||
authors = ["Martin Berg Alstad"]
|
authors = ["Martin Berg Alstad"]
|
||||||
homepage = "martials.no"
|
homepage = "emberal.github.io"
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "lib"
|
name = "lib"
|
||||||
version = "2.0.0"
|
version = "1.4.3"
|
||||||
description = "A library with utilities and helper fuctions."
|
description = "A library with utilities and helper fuctions."
|
||||||
edition = { workspace = true }
|
edition = { workspace = true }
|
||||||
rust-version = { workspace = true }
|
rust-version = { workspace = true }
|
||||||
@ -21,19 +21,18 @@ homepage = { workspace = true }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# Api
|
# Api
|
||||||
axum = { version = "0.8", optional = true, features = ["multipart"] }
|
axum = { version = "0.7", optional = true, features = ["multipart"] }
|
||||||
tower = { version = "0.5", optional = true }
|
tower = { version = "0.5", optional = true }
|
||||||
tower-http = { version = "0.6", optional = true, features = ["trace", "cors", "normalize-path"] }
|
tower-http = { version = "0.5", optional = true, features = ["trace", "cors", "normalize-path"] }
|
||||||
mime = { version = "0.3", optional = true }
|
mime = { version = "0.3", optional = true }
|
||||||
# Async
|
# Async
|
||||||
tokio = { workspace = true, optional = true, features = ["fs", "rt-multi-thread"] }
|
tokio = { workspace = true, optional = true, features = ["fs", "rt-multi-thread"] }
|
||||||
tokio-util = { version = "0.7", optional = true, features = ["io"] }
|
tokio-util = { version = "0.7", optional = true, features = ["io"] }
|
||||||
# Database
|
# Database
|
||||||
diesel = { workspace = true, optional = true, features = ["postgres"] }
|
diesel = { workspace = true, optional = true, features = ["postgres"] }
|
||||||
diesel-async = { workspace = true, optional = true, features = ["postgres", "deadpool", "async-connection-wrapper"] }
|
diesel-async = { workspace = true, optional = true, features = ["postgres", "deadpool"] }
|
||||||
diesel-crud-derive = { path = "crates/diesel_crud_derive", optional = true }
|
diesel-crud-derive = { path = "crates/diesel_crud_derive", optional = true }
|
||||||
diesel-crud-trait = { path = "crates/diesel_crud_trait", optional = true }
|
diesel-crud-trait = { path = "crates/diesel_crud_trait", optional = true }
|
||||||
diesel_migrations = { workspace = true, optional = true }
|
|
||||||
deadpool-diesel = { workspace = true, optional = true, features = ["postgres"] }
|
deadpool-diesel = { workspace = true, optional = true, features = ["postgres"] }
|
||||||
# Error handling
|
# Error handling
|
||||||
thiserror = { workspace = true, optional = true }
|
thiserror = { workspace = true, optional = true }
|
||||||
@ -41,15 +40,12 @@ thiserror = { workspace = true, optional = true }
|
|||||||
tracing = { version = "0.1", optional = true }
|
tracing = { version = "0.1", optional = true }
|
||||||
tracing-subscriber = { version = "0.3", optional = true }
|
tracing-subscriber = { version = "0.3", optional = true }
|
||||||
# Parsing
|
# Parsing
|
||||||
nom = { version = "8.0", optional = true }
|
nom = { version = "7.1", optional = true }
|
||||||
# Procedural macros
|
# Procedural macros
|
||||||
into-response-derive = { path = "crates/into_response_derive", optional = true }
|
into-response-derive = { path = "crates/into_response_derive", optional = true }
|
||||||
read-files = { path = "crates/read_files", optional = true }
|
read-files = { path = "crates/read_files", optional = true }
|
||||||
# Serialization / Deserialization
|
# Serialization / Deserialization
|
||||||
serde = { version = "1.0", optional = true, features = ["derive"] }
|
serde = { version = "1.0", optional = true, features = ["derive"] }
|
||||||
serde_json = { version = "1.0", optional = true }
|
|
||||||
# Test
|
|
||||||
testcontainers-modules = { workspace = true, features = ["postgres"], optional = true }
|
|
||||||
# Time
|
# Time
|
||||||
chrono = { version = "0.4", optional = true, features = ["serde"] }
|
chrono = { version = "0.4", optional = true, features = ["serde"] }
|
||||||
# Utils
|
# Utils
|
||||||
@ -61,29 +57,24 @@ tokio = "1.40"
|
|||||||
# Database
|
# Database
|
||||||
diesel = "2.2"
|
diesel = "2.2"
|
||||||
diesel-async = "0.5"
|
diesel-async = "0.5"
|
||||||
diesel_migrations = "2.2"
|
|
||||||
deadpool-diesel = "0.6"
|
deadpool-diesel = "0.6"
|
||||||
# Error handling
|
# Error handling
|
||||||
thiserror = "2.0"
|
thiserror = "1.0"
|
||||||
# Procedural macros
|
# Procedural macros
|
||||||
syn = "2.0"
|
syn = "2.0"
|
||||||
quote = "1.0"
|
quote = "1.0"
|
||||||
deluxe = "0.5"
|
deluxe = "0.5"
|
||||||
proc-macro2 = "1.0"
|
proc-macro2 = "1.0"
|
||||||
# Test
|
|
||||||
testcontainers-modules = "0.11"
|
|
||||||
# Utils
|
# Utils
|
||||||
derive_more = "2.0"
|
derive_more = "1.0"
|
||||||
regex = "1.11"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
axum = ["dep:axum", "dep:tower", "dep:tower-http", "dep:thiserror", "dep:tracing", "dep:tracing-subscriber", "dep:tokio", "dep:mime"]
|
axum = ["dep:axum", "dep:tower", "dep:tower-http", "dep:thiserror", "dep:tracing", "dep:tracing-subscriber", "dep:tokio", "dep:mime"]
|
||||||
diesel = ["dep:diesel-crud-trait", "dep:diesel", "dep:diesel-async", "dep:deadpool-diesel", "dep:diesel_migrations"]
|
diesel = ["dep:diesel-crud-trait", "dep:diesel", "dep:diesel-async", "dep:deadpool-diesel"]
|
||||||
io = ["dep:tokio", "dep:tokio-util"]
|
io = ["dep:tokio", "dep:tokio-util"]
|
||||||
iter = []
|
iter = []
|
||||||
nom = ["dep:nom"]
|
nom = ["dep:nom"]
|
||||||
serde = ["dep:serde", "dep:serde_json"]
|
serde = ["dep:serde"]
|
||||||
derive = ["dep:into-response-derive", "dep:diesel-crud-derive"]
|
derive = ["dep:into-response-derive", "dep:diesel-crud-derive"]
|
||||||
read-files = ["dep:read-files"]
|
read-files = ["dep:read-files"]
|
||||||
time = ["dep:chrono"]
|
time = ["dep:chrono"]
|
||||||
test = ["dep:testcontainers-modules"]
|
|
||||||
|
15
Makefile.toml
Normal file
15
Makefile.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[tasks.clippy]
|
||||||
|
command = "cargo"
|
||||||
|
args = ["clippy", "--all-targets", "--all-features", "--", "-D", "warnings"]
|
||||||
|
|
||||||
|
[tasks.fmt]
|
||||||
|
command = "cargo"
|
||||||
|
args = ["fmt", "--all"]
|
||||||
|
|
||||||
|
[tasks.test]
|
||||||
|
command = "cargo"
|
||||||
|
args = ["test", "--all-features"]
|
||||||
|
|
||||||
|
[tasks.coverage]
|
||||||
|
command = "cargo"
|
||||||
|
args = ["llvm-cov", "--all-features"]
|
@ -1,3 +1,3 @@
|
|||||||
# Rust Lib 🦀
|
# Lib
|
||||||
|
|
||||||
Rust library for common code, traits and utility functions
|
-_-
|
||||||
|
@ -9,6 +9,6 @@ pub(crate) struct PrimaryKey {
|
|||||||
|
|
||||||
pub(crate) fn return_type(output: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
pub(crate) fn return_type(output: proc_macro2::TokenStream) -> proc_macro2::TokenStream {
|
||||||
quote! {
|
quote! {
|
||||||
Result<#output, lib::diesel_crud_trait::CrudError>
|
std::pin::Pin<Box<dyn core::future::Future<Output = Result<#output, lib::diesel_crud_trait::CrudError>> + Send + 'async_trait>>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Attributes, common};
|
use crate::{common, Attributes};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
pub(crate) fn derive_diesel_crud_create_impl(
|
pub(crate) fn derive_diesel_crud_create_impl(
|
||||||
@ -16,24 +16,37 @@ pub(crate) fn derive_diesel_crud_create_impl(
|
|||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl lib::diesel_crud_trait::DieselCrudCreate<#table::table> for #struct_ident {
|
impl lib::diesel_crud_trait::DieselCrudCreate<#table::table> for #struct_ident {
|
||||||
type Insert = #insert;
|
type Insert = #insert;
|
||||||
async fn insert(insert: Self::Insert, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
|
fn insert<'a, 'async_trait>(insert: Self::Insert, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type
|
||||||
use diesel::associations::HasTable;
|
where
|
||||||
diesel_async::RunQueryDsl::get_result(
|
Self: Sized + Sync + 'a,
|
||||||
diesel::dsl::insert_into(#table::table::table()).values(insert),
|
'a: 'async_trait,
|
||||||
conn
|
{
|
||||||
)
|
Box::pin(async move {
|
||||||
.await
|
use diesel::associations::HasTable;
|
||||||
.map_err(Into::into)
|
diesel_async::RunQueryDsl::get_result(
|
||||||
|
diesel::dsl::insert_into(#table::table::table()).values(insert),
|
||||||
|
conn
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn insert_many(insert: &[Self::Insert], conn: &mut diesel_async::AsyncPgConnection) -> #many_return_type {
|
fn insert_many<'a, 'b, 'async_trait>(insert: &'a [Self::Insert], conn: &'b mut diesel_async::AsyncPgConnection) -> #many_return_type
|
||||||
use diesel::associations::HasTable;
|
where
|
||||||
diesel_async::RunQueryDsl::get_results(
|
Self: Sized + Sync + 'async_trait,
|
||||||
diesel::dsl::insert_into(#table::table::table()).values(insert),
|
'a: 'async_trait,
|
||||||
conn
|
'b: 'async_trait,
|
||||||
)
|
{
|
||||||
.await
|
Box::pin(async move {
|
||||||
.map_err(Into::into)
|
use diesel::associations::HasTable;
|
||||||
|
diesel_async::RunQueryDsl::get_results(
|
||||||
|
diesel::dsl::insert_into(#table::table::table()).values(insert),
|
||||||
|
conn
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Attributes, PrimaryKey, common};
|
use crate::{common, Attributes, PrimaryKey};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
pub(crate) fn derive_diesel_crud_delete_impl(
|
pub(crate) fn derive_diesel_crud_delete_impl(
|
||||||
@ -22,18 +22,24 @@ pub(crate) fn derive_diesel_crud_delete_impl(
|
|||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl lib::diesel_crud_trait::DieselCrudDelete for #struct_ident {
|
impl lib::diesel_crud_trait::DieselCrudDelete for #struct_ident {
|
||||||
type PK = #pk_type;
|
type PK = #pk_type;
|
||||||
async fn delete(pk: Self::PK, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
|
fn delete<'a, 'async_trait>(pk: Self::PK, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type
|
||||||
use diesel::QueryDsl;
|
where
|
||||||
use diesel::associations::HasTable;
|
Self: Sized + Sync + 'a,
|
||||||
diesel_async::RunQueryDsl::get_result(
|
'a: 'async_trait,
|
||||||
diesel::delete(
|
{
|
||||||
#table::table
|
Box::pin(async move {
|
||||||
.filter(diesel::expression_methods::ExpressionMethods::eq(#table::#pk_ident, pk))
|
use diesel::QueryDsl;
|
||||||
),
|
use diesel::associations::HasTable;
|
||||||
conn,
|
diesel_async::RunQueryDsl::get_result(
|
||||||
)
|
diesel::delete(
|
||||||
.await
|
#table::table
|
||||||
.map_err(Into::into)
|
.filter(diesel::expression_methods::ExpressionMethods::eq(#table::#pk_ident, pk))
|
||||||
|
),
|
||||||
|
conn,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Attributes, common};
|
use crate::{common, Attributes};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
pub(crate) fn derive_diesel_crud_list_impl(
|
pub(crate) fn derive_diesel_crud_list_impl(
|
||||||
@ -13,9 +13,15 @@ pub(crate) fn derive_diesel_crud_list_impl(
|
|||||||
quote! {
|
quote! {
|
||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl lib::diesel_crud_trait::DieselCrudList for #struct_ident {
|
impl lib::diesel_crud_trait::DieselCrudList for #struct_ident {
|
||||||
async fn list(conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
|
fn list<'a, 'async_trait>(conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type
|
||||||
use diesel::associations::HasTable;
|
where
|
||||||
diesel_async::RunQueryDsl::get_results(#table::table::table(), conn).await.map_err(Into::into)
|
Self: Sized + Sync + 'a,
|
||||||
|
'a: 'async_trait
|
||||||
|
{
|
||||||
|
Box::pin(async move {
|
||||||
|
use diesel::associations::HasTable;
|
||||||
|
diesel_async::RunQueryDsl::get_results(#table::table::table(), conn).await.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::common::PrimaryKey;
|
use crate::common::PrimaryKey;
|
||||||
use crate::{Attributes, common};
|
use crate::{common, Attributes};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
pub(crate) fn derive_diesel_crud_read_impl(
|
pub(crate) fn derive_diesel_crud_read_impl(
|
||||||
@ -20,14 +20,20 @@ pub(crate) fn derive_diesel_crud_read_impl(
|
|||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl lib::diesel_crud_trait::DieselCrudRead for #struct_ident {
|
impl lib::diesel_crud_trait::DieselCrudRead for #struct_ident {
|
||||||
type PK = #pk_type;
|
type PK = #pk_type;
|
||||||
async fn read(pk: Self::PK, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
|
fn read<'a, 'async_trait>(pk: Self::PK, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type
|
||||||
use diesel::associations::HasTable;
|
where
|
||||||
diesel_async::RunQueryDsl::get_result(
|
Self: Sized + Sync + 'a,
|
||||||
diesel::QueryDsl::find(#table::table::table(), pk),
|
'a: 'async_trait
|
||||||
conn
|
{
|
||||||
)
|
Box::pin(async move {
|
||||||
.await
|
use diesel::associations::HasTable;
|
||||||
.map_err(Into::into)
|
diesel_async::RunQueryDsl::get_result(
|
||||||
|
diesel::QueryDsl::find(#table::table::table(), pk),
|
||||||
|
conn
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::{Attributes, common};
|
use crate::{common, Attributes};
|
||||||
use quote::quote;
|
use quote::quote;
|
||||||
|
|
||||||
pub(crate) fn derive_diesel_crud_update_impl(
|
pub(crate) fn derive_diesel_crud_update_impl(
|
||||||
@ -15,14 +15,20 @@ pub(crate) fn derive_diesel_crud_update_impl(
|
|||||||
#[automatically_derived]
|
#[automatically_derived]
|
||||||
impl lib::diesel_crud_trait::DieselCrudUpdate for #struct_ident {
|
impl lib::diesel_crud_trait::DieselCrudUpdate for #struct_ident {
|
||||||
type Update = #update;
|
type Update = #update;
|
||||||
async fn update(update: Self::Update, conn: &mut diesel_async::AsyncPgConnection) -> #return_type {
|
fn update<'a, 'async_trait>(update: Self::Update, conn: &'a mut diesel_async::AsyncPgConnection) -> #return_type
|
||||||
use diesel::associations::HasTable;
|
where
|
||||||
diesel_async::RunQueryDsl::get_result(
|
Self: Sized + Sync + 'a,
|
||||||
diesel::dsl::update(#table::table::table()).set(update),
|
'a: 'async_trait,
|
||||||
conn,
|
{
|
||||||
)
|
Box::pin(async move {
|
||||||
.await
|
use diesel::associations::HasTable;
|
||||||
.map_err(Into::into)
|
diesel_async::RunQueryDsl::get_result(
|
||||||
|
diesel::dsl::update(#table::table::table()).set(update),
|
||||||
|
conn,
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
.map_err(Into::into)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,4 +7,6 @@ rust-version = { workspace = true }
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
diesel = { workspace = true, features = ["postgres"] }
|
diesel = { workspace = true, features = ["postgres"] }
|
||||||
diesel-async = { workspace = true, features = ["postgres", "deadpool"] }
|
diesel-async = { workspace = true, features = ["postgres", "deadpool"] }
|
||||||
thiserror = { workspace = true }
|
async-trait = "0.1"
|
||||||
|
deadpool-diesel = { version = "0.6", features = ["postgres"] }
|
||||||
|
thiserror = "1.0"
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
mod error;
|
mod error;
|
||||||
|
|
||||||
|
use async_trait::async_trait;
|
||||||
use diesel::{AsChangeset, Insertable};
|
use diesel::{AsChangeset, Insertable};
|
||||||
use diesel_async::AsyncPgConnection;
|
use diesel_async::AsyncPgConnection;
|
||||||
pub use error::CrudError;
|
pub use error::CrudError;
|
||||||
@ -27,19 +28,17 @@ pub trait DieselCrud<Table>:
|
|||||||
/// - `conn` - The database connection
|
/// - `conn` - The database connection
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A result containing the inserted entity or a `CrudError`
|
/// A result containing the inserted entity or a `CrudError`
|
||||||
|
#[async_trait]
|
||||||
pub trait DieselCrudCreate<Table>
|
pub trait DieselCrudCreate<Table>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
type Insert: Insertable<Table>;
|
type Insert: Insertable<Table>;
|
||||||
fn insert(
|
async fn insert(insert: Self::Insert, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>;
|
||||||
insert: Self::Insert,
|
async fn insert_many(
|
||||||
conn: &mut AsyncPgConnection,
|
|
||||||
) -> impl Future<Output = Result<Self, CrudError>>;
|
|
||||||
fn insert_many(
|
|
||||||
insert: &[Self::Insert],
|
insert: &[Self::Insert],
|
||||||
conn: &mut AsyncPgConnection,
|
conn: &mut AsyncPgConnection,
|
||||||
) -> impl Future<Output = Result<Vec<Self>, CrudError>>;
|
) -> Result<Vec<Self>, CrudError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets an entity from the database
|
/// Gets an entity from the database
|
||||||
@ -53,15 +52,13 @@ where
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
/// A result containing the entity or a `CrudError`.
|
/// A result containing the entity or a `CrudError`.
|
||||||
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
||||||
|
#[async_trait]
|
||||||
pub trait DieselCrudRead
|
pub trait DieselCrudRead
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
type PK;
|
type PK;
|
||||||
fn read(
|
async fn read(pk: Self::PK, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>;
|
||||||
pk: Self::PK,
|
|
||||||
conn: &mut AsyncPgConnection,
|
|
||||||
) -> impl Future<Output = Result<Self, CrudError>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Updates an entity in the database
|
/// Updates an entity in the database
|
||||||
@ -76,15 +73,13 @@ where
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
/// A result containing the old entry of the entity if successful or a `CrudError`.
|
/// A result containing the old entry of the entity if successful or a `CrudError`.
|
||||||
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
||||||
|
#[async_trait]
|
||||||
pub trait DieselCrudUpdate
|
pub trait DieselCrudUpdate
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
type Update: AsChangeset;
|
type Update: AsChangeset;
|
||||||
fn update(
|
async fn update(update: Self::Update, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>;
|
||||||
update: Self::Update,
|
|
||||||
conn: &mut AsyncPgConnection,
|
|
||||||
) -> impl Future<Output = Result<Self, CrudError>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deletes an entity from the database
|
/// Deletes an entity from the database
|
||||||
@ -98,15 +93,13 @@ where
|
|||||||
/// # Returns
|
/// # Returns
|
||||||
/// A result containing the deleted entity or a `CrudError`.
|
/// A result containing the deleted entity or a `CrudError`.
|
||||||
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
/// If the entity is not found, the error should be `CrudError::NotFound`.
|
||||||
|
#[async_trait]
|
||||||
pub trait DieselCrudDelete
|
pub trait DieselCrudDelete
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
type PK;
|
type PK;
|
||||||
fn delete(
|
async fn delete(pk: Self::PK, conn: &mut AsyncPgConnection) -> Result<Self, CrudError>;
|
||||||
pk: Self::PK,
|
|
||||||
conn: &mut AsyncPgConnection,
|
|
||||||
) -> impl Future<Output = Result<Self, CrudError>>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lists all entities in the table
|
/// Lists all entities in the table
|
||||||
@ -116,9 +109,10 @@ where
|
|||||||
/// - `conn` - The database connection
|
/// - `conn` - The database connection
|
||||||
/// # Returns
|
/// # Returns
|
||||||
/// A result containing a Vec of entities or a `CrudError`.
|
/// A result containing a Vec of entities or a `CrudError`.
|
||||||
|
#[async_trait]
|
||||||
pub trait DieselCrudList
|
pub trait DieselCrudList
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
fn list(conn: &mut AsyncPgConnection) -> impl Future<Output = Result<Vec<Self>, CrudError>>;
|
async fn list(conn: &mut AsyncPgConnection) -> Result<Vec<Self>, CrudError>;
|
||||||
}
|
}
|
||||||
|
@ -10,4 +10,4 @@ proc-macro = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
syn = { workspace = true }
|
syn = { workspace = true }
|
||||||
quote = { workspace = true }
|
quote = { workspace = true }
|
||||||
regex = { workspace = true }
|
regex = "1.10"
|
||||||
|
@ -9,9 +9,10 @@ homepage.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
diesel = { workspace = true }
|
diesel = { workspace = true }
|
||||||
diesel-async = { workspace = true }
|
diesel-async = { workspace = true }
|
||||||
lib = { path = "../../../rust-lib", features = ["diesel", "derive", "test"] }
|
lib = { path = "../../../rust-lib", features = ["diesel", "derive"] }
|
||||||
|
derive_more = { workspace = true, features = ["constructor", "from"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tokio = { workspace = true, features = ["macros"] }
|
tokio = { workspace = true, features = ["macros"] }
|
||||||
testcontainers-modules = { workspace = true, features = ["postgres"] }
|
testcontainers-modules = { version = "0.9", features = ["postgres"] }
|
||||||
diesel_migrations = { workspace = true }
|
diesel_async_migrations = "0.14"
|
||||||
|
@ -2,8 +2,8 @@
|
|||||||
# see https://diesel.rs/guides/configuring-diesel-cli
|
# see https://diesel.rs/guides/configuring-diesel-cli
|
||||||
|
|
||||||
[print_schema]
|
[print_schema]
|
||||||
file = "tests/schema.rs"
|
file = "src/schema.rs"
|
||||||
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
custom_type_derives = ["diesel::query_builder::QueryId", "Clone"]
|
||||||
|
|
||||||
[migrations_directory]
|
[migrations_directory]
|
||||||
dir = "./migrations"
|
dir = "/home/martin/git/rust/lib/crates/tests/migrations"
|
||||||
|
@ -5,9 +5,15 @@ use lib::diesel_crud_derive::{
|
|||||||
use lib::diesel_crud_trait::DieselCrudCreate;
|
use lib::diesel_crud_trait::DieselCrudCreate;
|
||||||
use test_containers::create_test_containers_pool;
|
use test_containers::create_test_containers_pool;
|
||||||
|
|
||||||
mod schema;
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test_containers;
|
pub mod test_containers;
|
||||||
|
|
||||||
|
diesel::table! {
|
||||||
|
user (email) {
|
||||||
|
#[max_length = 255]
|
||||||
|
email -> Varchar,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
Debug,
|
Debug,
|
||||||
@ -23,19 +29,19 @@ mod test_containers;
|
|||||||
DieselCrudUpdate,
|
DieselCrudUpdate,
|
||||||
)]
|
)]
|
||||||
#[diesel_crud(insert = InsertUser)]
|
#[diesel_crud(insert = InsertUser)]
|
||||||
#[diesel(table_name = schema::user)]
|
#[diesel(table_name = user)]
|
||||||
struct User {
|
struct User {
|
||||||
#[diesel_crud(pk)]
|
#[diesel_crud(pk)]
|
||||||
email: String,
|
email: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Insertable)]
|
#[derive(Clone, Insertable)]
|
||||||
#[diesel(table_name = schema::user)]
|
#[diesel(table_name = user)]
|
||||||
struct InsertUser {
|
struct InsertUser {
|
||||||
email: String,
|
email: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
#[tokio::test]
|
||||||
async fn test_insert_user() {
|
async fn test_insert_user() {
|
||||||
let container = create_test_containers_pool().await.unwrap();
|
let container = create_test_containers_pool().await.unwrap();
|
||||||
let mut conn = container.pool.get().await.unwrap();
|
let mut conn = container.pool.get().await.unwrap();
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
diesel::table! {
|
|
||||||
user (email) {
|
|
||||||
#[max_length = 255]
|
|
||||||
email -> Varchar,
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,11 +1,50 @@
|
|||||||
use diesel_migrations::EmbeddedMigrations;
|
use derive_more::{Constructor, From};
|
||||||
use lib::diesel::migration::run_migrations;
|
use diesel_async::pooled_connection::deadpool::{BuildError, PoolError};
|
||||||
use lib::test::test_containers::{ContainerError, TestContainer};
|
use diesel_async::AsyncPgConnection;
|
||||||
|
use diesel_async_migrations::EmbeddedMigrations;
|
||||||
|
use lib::diesel::pool::{create_pool_from_url, PgPool};
|
||||||
|
use lib::diesel::DieselError;
|
||||||
|
use testcontainers_modules::postgres::Postgres;
|
||||||
|
use testcontainers_modules::testcontainers::runners::AsyncRunner;
|
||||||
|
use testcontainers_modules::testcontainers::{ContainerAsync, TestcontainersError};
|
||||||
|
|
||||||
pub async fn create_test_containers_pool() -> Result<TestContainer, ContainerError> {
|
/// When the TestContainer is dropped, the container will be removed.
|
||||||
let test_container = lib::test::test_containers::create_test_containers_pool().await?;
|
/// # Errors
|
||||||
let connection = test_container.pool.get().await?;
|
/// If destructed and the container field is dropped, the container will be stopped
|
||||||
const MIGRATIONS: EmbeddedMigrations = diesel_migrations::embed_migrations!("./migrations");
|
/// and all connections from the pool will result in DatabaseError.
|
||||||
run_migrations(connection, MIGRATIONS).await?;
|
#[derive(Constructor)]
|
||||||
Ok(test_container)
|
pub struct TestContainer {
|
||||||
|
pub container: ContainerAsync<Postgres>,
|
||||||
|
pub pool: PgPool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, From)]
|
||||||
|
pub enum ContainerError {
|
||||||
|
TestContainers(TestcontainersError),
|
||||||
|
BuildError(BuildError),
|
||||||
|
PoolError(PoolError),
|
||||||
|
DieselError(DieselError),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_test_containers_pool<'a>() -> Result<TestContainer, ContainerError> {
|
||||||
|
let container = create_postgres_container().await?;
|
||||||
|
let connection_string = format!(
|
||||||
|
"postgres://postgres:postgres@localhost:{}/postgres",
|
||||||
|
container.get_host_port_ipv4(5432).await?
|
||||||
|
);
|
||||||
|
let pool = create_pool_from_url(connection_string)?;
|
||||||
|
run_migrations(pool.get().await?.as_mut()).await?;
|
||||||
|
Ok(TestContainer::new(container, pool))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn run_migrations(
|
||||||
|
conn: &mut AsyncPgConnection,
|
||||||
|
) -> Result<(), diesel::result::Error> {
|
||||||
|
static EMBEDDED_MIGRATIONS: EmbeddedMigrations =
|
||||||
|
diesel_async_migrations::embed_migrations!("./migrations");
|
||||||
|
EMBEDDED_MIGRATIONS.run_pending_migrations(conn).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn create_postgres_container() -> Result<ContainerAsync<Postgres>, TestcontainersError> {
|
||||||
|
Postgres::default().start().await
|
||||||
}
|
}
|
||||||
|
3
examples/multipart_file/Cargo.lock
generated
3
examples/multipart_file/Cargo.lock
generated
@ -1,6 +1,6 @@
|
|||||||
# This file is automatically @generated by Cargo.
|
# This file is automatically @generated by Cargo.
|
||||||
# It is not intended for manual editing.
|
# It is not intended for manual editing.
|
||||||
version = 3
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "addr2line"
|
name = "addr2line"
|
||||||
@ -308,7 +308,6 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
name = "lib"
|
name = "lib"
|
||||||
version = "1.4.3"
|
version = "1.4.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"async-trait",
|
|
||||||
"axum",
|
"axum",
|
||||||
"derive_more",
|
"derive_more",
|
||||||
"mime",
|
"mime",
|
||||||
|
44
flake.lock
generated
44
flake.lock
generated
@ -1,44 +0,0 @@
|
|||||||
{
|
|
||||||
"nodes": {
|
|
||||||
"nixpkgs": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1741196730,
|
|
||||||
"narHash": "sha256-0Sj6ZKjCpQMfWnN0NURqRCQn2ob7YtXTAOTwCuz7fkA=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "48913d8f9127ea6530a2a2f1bd4daa1b8685d8a3",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-24.11",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"nixpkgs-unstable": {
|
|
||||||
"locked": {
|
|
||||||
"lastModified": 1741173522,
|
|
||||||
"narHash": "sha256-k7VSqvv0r1r53nUI/IfPHCppkUAddeXn843YlAC5DR0=",
|
|
||||||
"owner": "NixOS",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"rev": "d69ab0d71b22fa1ce3dbeff666e6deb4917db049",
|
|
||||||
"type": "github"
|
|
||||||
},
|
|
||||||
"original": {
|
|
||||||
"owner": "NixOS",
|
|
||||||
"ref": "nixos-unstable",
|
|
||||||
"repo": "nixpkgs",
|
|
||||||
"type": "github"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": {
|
|
||||||
"inputs": {
|
|
||||||
"nixpkgs": "nixpkgs",
|
|
||||||
"nixpkgs-unstable": "nixpkgs-unstable"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"root": "root",
|
|
||||||
"version": 7
|
|
||||||
}
|
|
38
flake.nix
38
flake.nix
@ -1,38 +0,0 @@
|
|||||||
{
|
|
||||||
inputs = {
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";
|
|
||||||
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
|
|
||||||
};
|
|
||||||
|
|
||||||
outputs = { nixpkgs, nixpkgs-unstable, ... }:
|
|
||||||
let
|
|
||||||
system = "x86_64-linux";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
devShells.${system}.default =
|
|
||||||
let
|
|
||||||
pkgs = import nixpkgs {
|
|
||||||
inherit system;
|
|
||||||
};
|
|
||||||
unstable = import nixpkgs-unstable {
|
|
||||||
inherit system;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
pkgs.mkShell {
|
|
||||||
packages = with pkgs; [
|
|
||||||
git
|
|
||||||
just
|
|
||||||
] ++ [
|
|
||||||
# Rust
|
|
||||||
gcc
|
|
||||||
# cargo
|
|
||||||
] ++ [
|
|
||||||
# Diesel
|
|
||||||
diesel-cli
|
|
||||||
unstable.libpq
|
|
||||||
];
|
|
||||||
|
|
||||||
shellHook = "fish";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
19
justfile
19
justfile
@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/env just --justfile
|
|
||||||
|
|
||||||
run:
|
|
||||||
cargo run
|
|
||||||
|
|
||||||
fmt:
|
|
||||||
cargo fmt --all
|
|
||||||
|
|
||||||
lint:
|
|
||||||
cargo clippy --all-targets --all-features -- -D warnings
|
|
||||||
|
|
||||||
release:
|
|
||||||
cargo build --release
|
|
||||||
|
|
||||||
test:
|
|
||||||
cargo test --all-features --workspace
|
|
||||||
|
|
||||||
coverage:
|
|
||||||
cargo llvm-cov
|
|
@ -1,22 +1,23 @@
|
|||||||
use axum::Router;
|
use {
|
||||||
use axum::ServiceExt;
|
axum::{
|
||||||
use axum::extract::Request;
|
extract::Request, handler::Handler, response::IntoResponse, routing::Route, Router,
|
||||||
use axum::handler::Handler;
|
ServiceExt,
|
||||||
use axum::response::IntoResponse;
|
},
|
||||||
use axum::routing::Route;
|
std::{
|
||||||
use std::convert::Infallible;
|
convert::Infallible,
|
||||||
use std::io;
|
io,
|
||||||
use std::net::IpAddr;
|
net::{IpAddr, Ipv4Addr, SocketAddr},
|
||||||
use std::net::Ipv4Addr;
|
},
|
||||||
use std::net::SocketAddr;
|
tokio::net::TcpListener,
|
||||||
use tokio::net::TcpListener;
|
tower::{layer::Layer, Service},
|
||||||
use tower::{Service, layer::Layer};
|
tower_http::{
|
||||||
use tower_http::cors::CorsLayer;
|
cors::CorsLayer,
|
||||||
use tower_http::normalize_path::NormalizePathLayer;
|
normalize_path::NormalizePathLayer,
|
||||||
use tower_http::trace;
|
trace,
|
||||||
use tower_http::trace::HttpMakeClassifier;
|
trace::{HttpMakeClassifier, TraceLayer},
|
||||||
use tower_http::trace::TraceLayer;
|
},
|
||||||
use tracing::{Level, info};
|
tracing::{info, Level},
|
||||||
|
};
|
||||||
|
|
||||||
// TODO trim trailing slash into macro > let _app = NormalizePathLayer::trim_trailing_slash().layer(create_app!(routes));
|
// TODO trim trailing slash into macro > let _app = NormalizePathLayer::trim_trailing_slash().layer(create_app!(routes));
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -68,8 +69,8 @@ impl AppBuilder {
|
|||||||
/// Adds a layer to the previously added routes
|
/// Adds a layer to the previously added routes
|
||||||
pub fn layer<L>(mut self, layer: L) -> Self
|
pub fn layer<L>(mut self, layer: L) -> Self
|
||||||
where
|
where
|
||||||
L: Layer<Route> + Clone + Send + Sync + 'static,
|
L: Layer<Route> + Clone + Send + 'static,
|
||||||
L::Service: Service<Request> + Clone + Send + Sync + 'static,
|
L::Service: Service<Request> + Clone + Send + 'static,
|
||||||
<L::Service as Service<Request>>::Response: IntoResponse + 'static,
|
<L::Service as Service<Request>>::Response: IntoResponse + 'static,
|
||||||
<L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
|
<L::Service as Service<Request>>::Error: Into<Infallible> + 'static,
|
||||||
<L::Service as Service<Request>>::Future: Send + 'static,
|
<L::Service as Service<Request>>::Future: Send + 'static,
|
||||||
@ -151,13 +152,11 @@ impl AppBuilder {
|
|||||||
let _ = fmt_trace(); // Allowed to fail
|
let _ = fmt_trace(); // Allowed to fail
|
||||||
let listener = self.listener().await?;
|
let listener = self.listener().await?;
|
||||||
|
|
||||||
let should_normalize = self.normalize_path.unwrap_or(true);
|
if self.normalize_path.unwrap_or(true) {
|
||||||
let app = self.build();
|
let app = NormalizePathLayer::trim_trailing_slash().layer(self.build());
|
||||||
|
|
||||||
if should_normalize {
|
|
||||||
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
|
|
||||||
axum::serve(listener, ServiceExt::<Request>::into_make_service(app)).await?;
|
axum::serve(listener, ServiceExt::<Request>::into_make_service(app)).await?;
|
||||||
} else {
|
} else {
|
||||||
|
let app = self.build();
|
||||||
axum::serve(listener, app.into_make_service()).await?;
|
axum::serve(listener, app.into_make_service()).await?;
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -200,7 +199,7 @@ mod tests {
|
|||||||
AppBuilder::new()
|
AppBuilder::new()
|
||||||
.socket((Ipv4Addr::LOCALHOST, 8080))
|
.socket((Ipv4Addr::LOCALHOST, 8080))
|
||||||
.routes([Router::new()])
|
.routes([Router::new()])
|
||||||
.fallback(async || "Fallback")
|
.fallback(|| async { "Fallback" })
|
||||||
.cors(CorsLayer::new())
|
.cors(CorsLayer::new())
|
||||||
.normalize_path(true)
|
.normalize_path(true)
|
||||||
.tracing(TraceLayer::new_for_http())
|
.tracing(TraceLayer::new_for_http())
|
||||||
|
@ -1,14 +0,0 @@
|
|||||||
use crate::axum::traits::BuildJson;
|
|
||||||
use axum::body::Body;
|
|
||||||
use axum::http::header::CONTENT_TYPE;
|
|
||||||
use axum::http::Request;
|
|
||||||
use mime::APPLICATION_JSON;
|
|
||||||
use serde::Serialize;
|
|
||||||
use serde_json::json;
|
|
||||||
|
|
||||||
impl BuildJson for axum::http::request::Builder {
|
|
||||||
fn json<T: Serialize>(self, body: T) -> Result<Request<Body>, axum::http::Error> {
|
|
||||||
self.header(CONTENT_TYPE, APPLICATION_JSON.as_ref())
|
|
||||||
.body(Body::new(json!(body).to_string()))
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,7 +1,8 @@
|
|||||||
use axum::{
|
use axum::{
|
||||||
|
async_trait,
|
||||||
extract::{
|
extract::{
|
||||||
FromRequest, Multipart, Request,
|
|
||||||
multipart::{Field, MultipartError, MultipartRejection},
|
multipart::{Field, MultipartError, MultipartRejection},
|
||||||
|
FromRequest, Multipart, Request,
|
||||||
},
|
},
|
||||||
response::IntoResponse,
|
response::IntoResponse,
|
||||||
};
|
};
|
||||||
@ -109,6 +110,7 @@ impl IntoResponse for MultipartFileRejection {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl<S> FromRequest<S> for MultipartFile
|
impl<S> FromRequest<S> for MultipartFile
|
||||||
where
|
where
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
@ -140,6 +142,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
impl<S> FromRequest<S> for MultipartFiles
|
impl<S> FromRequest<S> for MultipartFiles
|
||||||
where
|
where
|
||||||
S: Send + Sync,
|
S: Send + Sync,
|
||||||
@ -175,7 +178,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn get_files(mut multipart: Multipart) -> Result<Vec<File>, MultipartFileRejection> {
|
async fn get_files<'a>(mut multipart: Multipart) -> Result<Vec<File>, MultipartFileRejection> {
|
||||||
let mut files = vec![];
|
let mut files = vec![];
|
||||||
while let Some(field) = multipart.next_field().await? {
|
while let Some(field) = multipart.next_field().await? {
|
||||||
files.push(File::from_field(field).await?);
|
files.push(File::from_field(field).await?);
|
||||||
|
@ -1,11 +1,8 @@
|
|||||||
pub mod app;
|
pub mod app;
|
||||||
#[cfg(feature = "serde")]
|
|
||||||
pub mod builder;
|
|
||||||
pub mod extractor;
|
pub mod extractor;
|
||||||
pub mod load;
|
pub mod load;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub mod response;
|
pub mod response;
|
||||||
pub mod router;
|
pub mod router;
|
||||||
pub mod traits;
|
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub mod wrappers;
|
pub mod wrappers;
|
||||||
|
@ -1,14 +1,10 @@
|
|||||||
use {
|
use {
|
||||||
crate::{serde::response::BaseResponse, serde::traits::DeserializeInto},
|
crate::serde::response::BaseResponse,
|
||||||
axum::{
|
axum::{
|
||||||
Json,
|
|
||||||
body::to_bytes,
|
|
||||||
response::{IntoResponse, Response},
|
response::{IntoResponse, Response},
|
||||||
|
Json,
|
||||||
},
|
},
|
||||||
serde::{
|
serde::Serialize,
|
||||||
Serialize,
|
|
||||||
de::{DeserializeOwned, Error},
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
impl<T: Serialize> IntoResponse for BaseResponse<T> {
|
impl<T: Serialize> IntoResponse for BaseResponse<T> {
|
||||||
@ -17,15 +13,6 @@ impl<T: Serialize> IntoResponse for BaseResponse<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DeserializeInto for Response {
|
|
||||||
async fn deserialize_into<T: DeserializeOwned>(self) -> Result<T, serde_json::Error> {
|
|
||||||
let body = to_bytes(self.into_body(), usize::MAX).await.map_err(|e| {
|
|
||||||
serde_json::Error::custom(format!("Failed to read response body: {}", e))
|
|
||||||
})?;
|
|
||||||
serde_json::from_slice(&body)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use axum::http::header::CONTENT_TYPE;
|
use axum::http::header::CONTENT_TYPE;
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
/// use lib::router;
|
/// use lib::router;
|
||||||
/// async fn simplify(path: axum::extract::path::Path<String>) {}
|
/// async fn simplify(path: axum::extract::path::Path<String>) {}
|
||||||
/// router!("/simplify", lib::routes!(
|
/// router!("/simplify", lib::routes!(
|
||||||
/// get "/{exp}" => simplify,
|
/// get "/:exp" => simplify,
|
||||||
/// get "/table/{exp}" => async || {}
|
/// get "/table/:exp" => || async {}
|
||||||
/// ));
|
/// ));
|
||||||
/// ```
|
/// ```
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
@ -92,8 +92,8 @@ macro_rules! join_routes {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use axum::Router;
|
|
||||||
use axum::extract::State;
|
use axum::extract::State;
|
||||||
|
use axum::Router;
|
||||||
|
|
||||||
async fn index() {}
|
async fn index() {}
|
||||||
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
use axum::body::Body;
|
|
||||||
use axum::http::Request;
|
|
||||||
use serde::Serialize;
|
|
||||||
|
|
||||||
pub trait BuildJson {
|
|
||||||
fn json<T: Serialize>(self, body: T) -> Result<Request<Body>, axum::http::Error>;
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
use deadpool_diesel::Status;
|
|
||||||
use derive_more::From;
|
|
||||||
use diesel_async::AsyncPgConnection;
|
|
||||||
use diesel_async::pooled_connection::deadpool::{Object, PoolError};
|
|
||||||
use lib::diesel::pool::PgPool;
|
|
||||||
|
|
||||||
pub trait GetConnection: Clone + Send + Sync {
|
|
||||||
fn get(
|
|
||||||
&self,
|
|
||||||
) -> impl Future<Output = Result<Object<AsyncPgConnection>, GetConnectionError>> + Send;
|
|
||||||
fn status(&self) -> Status;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetConnection for PgPool {
|
|
||||||
async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError> {
|
|
||||||
self.get().await.map_err(Into::into)
|
|
||||||
}
|
|
||||||
#[inline]
|
|
||||||
fn status(&self) -> Status {
|
|
||||||
self.status()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, From)]
|
|
||||||
pub enum GetConnectionError {
|
|
||||||
PoolError(PoolError),
|
|
||||||
DieselError(diesel::result::Error),
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
use diesel::pg::Pg;
|
|
||||||
use diesel_async::AsyncConnection;
|
|
||||||
use diesel_async::async_connection_wrapper::AsyncConnectionWrapper;
|
|
||||||
use diesel_migrations::{EmbeddedMigrations, MigrationHarness};
|
|
||||||
use tokio::task::JoinError;
|
|
||||||
|
|
||||||
/// Run Diesel migrations using an async connection.
|
|
||||||
/// Only works with Postgres.
|
|
||||||
pub async fn run_migrations<A>(
|
|
||||||
async_connection: A,
|
|
||||||
migrations: EmbeddedMigrations,
|
|
||||||
) -> Result<(), JoinError>
|
|
||||||
where
|
|
||||||
A: AsyncConnection<Backend = Pg> + 'static,
|
|
||||||
{
|
|
||||||
let mut async_wrapper = AsyncConnectionWrapper::<A>::from(async_connection);
|
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
|
||||||
async_wrapper.run_pending_migrations(migrations).unwrap();
|
|
||||||
})
|
|
||||||
.await
|
|
||||||
}
|
|
@ -1,5 +1,3 @@
|
|||||||
pub mod get_connection;
|
|
||||||
pub mod migration;
|
|
||||||
pub mod pool;
|
pub mod pool;
|
||||||
|
|
||||||
/// Re-export diesel::result::Error as DieselError
|
/// Re-export diesel::result::Error as DieselError
|
||||||
|
@ -19,8 +19,6 @@ pub mod io;
|
|||||||
pub mod nom;
|
pub mod nom;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub mod serde;
|
pub mod serde;
|
||||||
#[cfg(feature = "test")]
|
|
||||||
pub mod test;
|
|
||||||
#[cfg(feature = "time")]
|
#[cfg(feature = "time")]
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod traits;
|
pub mod traits;
|
||||||
|
@ -1,22 +1,23 @@
|
|||||||
use nom::IResult;
|
use {
|
||||||
use nom::bytes::complete::take_while_m_n;
|
nom::{
|
||||||
use nom::character::complete::char;
|
bytes::complete::take_while_m_n,
|
||||||
use nom::character::complete::multispace0;
|
character::complete::{char, multispace0},
|
||||||
use nom::combinator::eof;
|
combinator::eof,
|
||||||
use nom::error::ParseError;
|
sequence::{delimited, terminated},
|
||||||
use nom::sequence::delimited;
|
IResult, InputIter, InputLength, InputTake, Slice,
|
||||||
use nom::sequence::terminated;
|
},
|
||||||
use nom::{Input, Parser};
|
std::ops::RangeFrom,
|
||||||
|
};
|
||||||
|
|
||||||
|
// TODO generic input
|
||||||
|
|
||||||
/// Trim leading and trailing whitespace from the input Parser
|
/// Trim leading and trailing whitespace from the input Parser
|
||||||
/// - Parameters
|
/// - Parameters
|
||||||
/// - `inner`: The parser to trim
|
/// - `inner`: The parser to trim
|
||||||
/// - Returns: A parser that trims leading and trailing whitespace from the input and then runs the value from the inner parser
|
/// - Returns: A parser that trims leading and trailing whitespace from the input and then runs the value from the inner parser
|
||||||
pub fn trim<I, O, F, E: ParseError<I>>(inner: F) -> impl Parser<I, Output = O, Error = E>
|
pub fn trim<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a str, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
Parser: FnMut(&'a str) -> IResult<&'a str, R>,
|
||||||
F: Parser<I, Output = O, Error = E>,
|
|
||||||
<I as Input>::Item: nom::AsChar,
|
|
||||||
{
|
{
|
||||||
delimited(multispace0, inner, multispace0)
|
delimited(multispace0, inner, multispace0)
|
||||||
}
|
}
|
||||||
@ -26,11 +27,9 @@ where
|
|||||||
/// - Parameters
|
/// - Parameters
|
||||||
/// - `inner`: The parser to run inside the parentheses
|
/// - `inner`: The parser to run inside the parentheses
|
||||||
/// - Returns: A parser that parses a parenthesized expression
|
/// - Returns: A parser that parses a parenthesized expression
|
||||||
pub fn parenthesized<I, O, F, E: ParseError<I>>(inner: F) -> impl Parser<I, Output = O, Error = E>
|
pub fn parenthesized<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a str, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
Parser: FnMut(&'a str) -> IResult<&'a str, R>,
|
||||||
F: Parser<I, Output = O, Error = E>,
|
|
||||||
<I as Input>::Item: nom::AsChar,
|
|
||||||
{
|
{
|
||||||
delimited(char('('), inner, char(')'))
|
delimited(char('('), inner, char(')'))
|
||||||
}
|
}
|
||||||
@ -40,10 +39,10 @@ where
|
|||||||
/// - `n`: The length of the string to take
|
/// - `n`: The length of the string to take
|
||||||
/// - `predicate`: The predicate to call to validate the input
|
/// - `predicate`: The predicate to call to validate the input
|
||||||
/// - Returns: A parser that takes `n` characters from the input
|
/// - Returns: A parser that takes `n` characters from the input
|
||||||
pub fn take_where<F, I>(n: usize, predicate: F) -> impl FnMut(I) -> IResult<I, I>
|
pub fn take_where<F, Input>(n: usize, predicate: F) -> impl Fn(Input) -> IResult<Input, Input>
|
||||||
where
|
where
|
||||||
I: Input,
|
Input: InputTake + InputIter + InputLength + Slice<RangeFrom<usize>>,
|
||||||
F: Fn(<I as Input>::Item) -> bool,
|
F: Fn(<Input as InputIter>::Item) -> bool + Copy,
|
||||||
{
|
{
|
||||||
take_while_m_n(n, n, predicate)
|
take_while_m_n(n, n, predicate)
|
||||||
}
|
}
|
||||||
@ -55,43 +54,40 @@ where
|
|||||||
/// - Returns: A parser that runs the inner parser and then the end of the input
|
/// - Returns: A parser that runs the inner parser and then the end of the input
|
||||||
/// # Example
|
/// # Example
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib::nom::combinators::exhausted;
|
|
||||||
/// use nom::bytes::complete::{tag};
|
/// use nom::bytes::complete::{tag};
|
||||||
/// use nom::Parser;
|
/// use lib::nom::combinators::exhausted;
|
||||||
///
|
///
|
||||||
/// let input = "test";
|
/// let input = "test";
|
||||||
/// let (remaining, result) = exhausted(tag::<&str, &str, nom::error::Error<&str>>("test")).parse(input).unwrap();
|
/// let (remaining, result) = exhausted(tag("test"))(input).unwrap();
|
||||||
/// assert_eq!(remaining, "");
|
/// assert_eq!(remaining, "");
|
||||||
/// assert_eq!(result, "test");
|
/// assert_eq!(result, "test");
|
||||||
/// ```
|
/// ```
|
||||||
/// - Fails if the input is not exhausted
|
/// - Fails if the input is not exhausted
|
||||||
/// ```
|
/// ```
|
||||||
/// use lib::nom::combinators::exhausted;
|
|
||||||
/// use nom::bytes::complete::{tag};
|
/// use nom::bytes::complete::{tag};
|
||||||
/// use nom::Parser;
|
/// use lib::nom::combinators::exhausted;
|
||||||
///
|
///
|
||||||
/// let input = "test";
|
/// let input = "test";
|
||||||
/// assert!(exhausted(tag::<&str, &str, nom::error::Error<&str>>("tes")).parse(input).is_err());
|
/// assert!(exhausted(tag("tes"))(input).is_err());
|
||||||
/// ```
|
/// ```
|
||||||
pub fn exhausted<F, I, O, E: ParseError<I>>(inner: F) -> impl Parser<I, Output = O, Error = E>
|
pub fn exhausted<'a, Parser, R>(inner: Parser) -> impl FnMut(&'a str) -> IResult<&'a str, R>
|
||||||
where
|
where
|
||||||
I: Input,
|
Parser: FnMut(&'a str) -> IResult<&'a str, R>,
|
||||||
F: Parser<I, Output = O, Error = E>,
|
|
||||||
{
|
{
|
||||||
terminated(inner, eof)
|
terminated(inner, eof)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use nom::{bytes::complete::take_while, sequence::tuple};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use nom::bytes::complete::take_while;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_trim_both_sides() {
|
fn test_trim_both_sides() {
|
||||||
let input = " test ";
|
let input = " test ";
|
||||||
let (remaining, result) = trim(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
let (remaining, result) =
|
||||||
.parse(input)
|
trim(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, "test");
|
assert_eq!(result, "test");
|
||||||
}
|
}
|
||||||
@ -99,9 +95,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_trim_leading() {
|
fn test_trim_leading() {
|
||||||
let input = " test";
|
let input = " test";
|
||||||
let (remaining, result) = trim(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
let (remaining, result) =
|
||||||
.parse(input)
|
trim(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, "test");
|
assert_eq!(result, "test");
|
||||||
}
|
}
|
||||||
@ -109,9 +104,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_trim_trailing() {
|
fn test_trim_trailing() {
|
||||||
let input = "test ";
|
let input = "test ";
|
||||||
let (remaining, result) = trim(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
let (remaining, result) =
|
||||||
.parse(input)
|
trim(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, "test");
|
assert_eq!(result, "test");
|
||||||
}
|
}
|
||||||
@ -119,9 +113,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_trim_no_trim() {
|
fn test_trim_no_trim() {
|
||||||
let input = "test";
|
let input = "test";
|
||||||
let (remaining, result) = trim(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
let (remaining, result) =
|
||||||
.parse(input)
|
trim(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, "test");
|
assert_eq!(result, "test");
|
||||||
}
|
}
|
||||||
@ -129,9 +122,8 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parenthesized() {
|
fn test_parenthesized() {
|
||||||
let input = "(test)";
|
let input = "(test)";
|
||||||
let (remaining, result) = parenthesized(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
let (remaining, result) =
|
||||||
.parse(input)
|
parenthesized(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, "test");
|
assert_eq!(result, "test");
|
||||||
}
|
}
|
||||||
@ -139,11 +131,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_parenthesized_parse_until_end() {
|
fn test_parenthesized_parse_until_end() {
|
||||||
let input = "(test)";
|
let input = "(test)";
|
||||||
assert!(
|
assert!(parenthesized(take_while(|_| true))(input).is_err());
|
||||||
parenthesized::<&str, &str, _, nom::error::Error<&str>>(take_while(|_| true))
|
|
||||||
.parse(input)
|
|
||||||
.is_err()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -164,7 +152,7 @@ mod tests {
|
|||||||
fn test_take_where_too_much() {
|
fn test_take_where_too_much() {
|
||||||
let input = "testing";
|
let input = "testing";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
take_where(4, |c: char| c.is_ascii_alphabetic()).parse(input),
|
take_where(4, |c: char| c.is_ascii_alphabetic())(input),
|
||||||
Ok(("ing", "test"))
|
Ok(("ing", "test"))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -172,19 +160,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_take_where_predicate_false() {
|
fn test_take_where_predicate_false() {
|
||||||
let input = "test";
|
let input = "test";
|
||||||
assert!(
|
assert!(take_where(4, |c: char| c.is_ascii_digit())(input).is_err());
|
||||||
take_where(4, |c: char| c.is_ascii_digit())
|
|
||||||
.parse(input)
|
|
||||||
.is_err()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exhausted() {
|
fn test_exhausted() {
|
||||||
let input = "test";
|
let input = "test";
|
||||||
let (remaining, result) = exhausted(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
let (remaining, result) =
|
||||||
.parse(input)
|
exhausted(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).unwrap();
|
||||||
.unwrap();
|
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, "test");
|
assert_eq!(result, "test");
|
||||||
}
|
}
|
||||||
@ -192,21 +175,16 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_exhausted_not_exhausted() {
|
fn test_exhausted_not_exhausted() {
|
||||||
let input = "test ";
|
let input = "test ";
|
||||||
assert!(
|
assert!(exhausted(take_where(4, |c: char| c.is_ascii_alphabetic()))(input).is_err());
|
||||||
exhausted(take_where(4, |c: char| c.is_ascii_alphabetic()))
|
|
||||||
.parse(input)
|
|
||||||
.is_err()
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_exhausted_tuple() {
|
fn test_exhausted_tuple() {
|
||||||
let input = "test";
|
let input = "test";
|
||||||
let (remaining, result) = exhausted((
|
let (remaining, result) = exhausted(tuple((
|
||||||
take_where(3, |c: char| c.is_ascii_alphabetic()),
|
take_where(3, |c: char| c.is_ascii_alphabetic()),
|
||||||
take_while(|c: char| c.is_ascii_alphabetic()),
|
take_while(|c: char| c.is_ascii_alphabetic()),
|
||||||
))
|
)))(input)
|
||||||
.parse(input)
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(remaining, "");
|
assert_eq!(remaining, "");
|
||||||
assert_eq!(result, ("tes", "t"));
|
assert_eq!(result, ("tes", "t"));
|
||||||
|
@ -1,2 +1 @@
|
|||||||
pub mod response;
|
pub mod response;
|
||||||
pub mod traits;
|
|
||||||
|
@ -1,7 +0,0 @@
|
|||||||
use serde::de::DeserializeOwned;
|
|
||||||
|
|
||||||
pub trait DeserializeInto {
|
|
||||||
fn deserialize_into<T: DeserializeOwned>(
|
|
||||||
self,
|
|
||||||
) -> impl Future<Output = Result<T, serde_json::Error>>;
|
|
||||||
}
|
|
@ -1,43 +0,0 @@
|
|||||||
use crate::diesel::DieselError;
|
|
||||||
use crate::diesel::get_connection::{GetConnection, GetConnectionError};
|
|
||||||
use crate::diesel::pool::PgPool;
|
|
||||||
use deadpool_diesel::Status;
|
|
||||||
use deadpool_diesel::postgres::BuildError;
|
|
||||||
use derive_more::From;
|
|
||||||
use diesel_async::pooled_connection::deadpool::Object;
|
|
||||||
use diesel_async::{AsyncConnection, AsyncPgConnection};
|
|
||||||
use lib::diesel::pool::create_pool_from_url_with_size;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct PoolStub(PgPool);
|
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, From)]
|
|
||||||
pub enum Error {
|
|
||||||
Connection(diesel::ConnectionError),
|
|
||||||
Database(DieselError),
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn setup_test_transaction(url: impl AsRef<str>) -> Result<AsyncPgConnection, Error> {
|
|
||||||
let mut conn = AsyncPgConnection::establish(url.as_ref()).await?;
|
|
||||||
conn.begin_test_transaction().await?;
|
|
||||||
Ok(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_test_pool_url_with_size(
|
|
||||||
url: impl Into<String>,
|
|
||||||
size: usize,
|
|
||||||
) -> Result<PoolStub, BuildError> {
|
|
||||||
let pool = create_pool_from_url_with_size(url, size)?;
|
|
||||||
Ok(PoolStub(pool))
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GetConnection for PoolStub {
|
|
||||||
async fn get(&self) -> Result<Object<AsyncPgConnection>, GetConnectionError> {
|
|
||||||
let mut conn = self.0.get().await?;
|
|
||||||
conn.begin_test_transaction().await?;
|
|
||||||
Ok(conn)
|
|
||||||
}
|
|
||||||
fn status(&self) -> Status {
|
|
||||||
unimplemented!("PoolStub does not support status")
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,3 +0,0 @@
|
|||||||
#[cfg(feature = "diesel")]
|
|
||||||
pub mod diesel_pool;
|
|
||||||
pub mod test_containers;
|
|
@ -1,45 +0,0 @@
|
|||||||
use crate::diesel::pool::{PgPool, create_pool_from_url};
|
|
||||||
use deadpool_diesel::postgres::BuildError;
|
|
||||||
use derive_more::{Constructor, From};
|
|
||||||
use diesel_async::pooled_connection::deadpool::PoolError;
|
|
||||||
use lib::diesel::DieselError;
|
|
||||||
use testcontainers_modules::postgres::Postgres;
|
|
||||||
use testcontainers_modules::testcontainers::runners::AsyncRunner;
|
|
||||||
use testcontainers_modules::testcontainers::{ContainerAsync, TestcontainersError};
|
|
||||||
use tokio::task::JoinError;
|
|
||||||
|
|
||||||
/// When the TestContainer is dropped, the container will be removed.
|
|
||||||
/// # Errors
|
|
||||||
/// If destructed and the container field is dropped, the container will be dropped, and using the pool will cause an error.
|
|
||||||
#[derive(Constructor)]
|
|
||||||
pub struct TestContainer {
|
|
||||||
pub container: ContainerAsync<Postgres>,
|
|
||||||
pub pool: PgPool,
|
|
||||||
}
|
|
||||||
|
|
||||||
const TEST_CONTAINERS_INTERNAL_PORT: u16 = 5432;
|
|
||||||
|
|
||||||
pub async fn create_test_containers_pool() -> Result<TestContainer, ContainerError> {
|
|
||||||
let container = create_postgres_container().await?;
|
|
||||||
let connection_string = format!(
|
|
||||||
"postgres://postgres:postgres@127.0.0.1:{}/postgres",
|
|
||||||
container
|
|
||||||
.get_host_port_ipv4(TEST_CONTAINERS_INTERNAL_PORT)
|
|
||||||
.await?
|
|
||||||
);
|
|
||||||
let pool = create_pool_from_url(connection_string)?;
|
|
||||||
Ok(TestContainer::new(container, pool))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub async fn create_postgres_container() -> Result<ContainerAsync<Postgres>, TestcontainersError> {
|
|
||||||
Postgres::default().start().await
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, From)]
|
|
||||||
pub enum ContainerError {
|
|
||||||
TestContainers(TestcontainersError),
|
|
||||||
BuildError(BuildError),
|
|
||||||
PoolError(PoolError),
|
|
||||||
DieselError(DieselError),
|
|
||||||
JoinError(JoinError),
|
|
||||||
}
|
|
@ -23,8 +23,9 @@
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! map {
|
macro_rules! map {
|
||||||
() => { std::collections::HashMap::new() };
|
() => { std::collections::HashMap::new() };
|
||||||
($default:ty; $($key:expr),+ $(,)?) => {
|
($default:ty; $($key:expr),* $(,)?) => {
|
||||||
{
|
{
|
||||||
|
#[allow(unused_mut)]
|
||||||
let mut temp_map = std::collections::HashMap::new();
|
let mut temp_map = std::collections::HashMap::new();
|
||||||
$(
|
$(
|
||||||
temp_map.insert($key, <$default>::default());
|
temp_map.insert($key, <$default>::default());
|
||||||
@ -75,8 +76,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_map_only_keys_1_key() {
|
fn test_map_only_keys_0_keys() {
|
||||||
let map: HashMap<usize, usize> = map!(usize; 1);
|
let map: HashMap<usize, usize> = map!(usize;);
|
||||||
assert_eq!(map.len(), 1);
|
assert_eq!(map.len(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user