Merge branch 'main' into wip

This commit is contained in:
Sebastian Hugentobler 2024-09-25 10:27:17 +02:00
commit 19202249b9
15 changed files with 332 additions and 1188 deletions

259
Cargo.lock generated
View File

@ -116,9 +116,9 @@ dependencies = [
[[package]] [[package]]
name = "anstyle" name = "anstyle"
version = "1.0.6" version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
@ -517,9 +517,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.6.0" version = "1.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3"
[[package]] [[package]]
name = "cc" name = "cc"
@ -549,7 +549,7 @@ dependencies = [
"iana-time-zone", "iana-time-zone",
"num-traits", "num-traits",
"serde", "serde",
"windows-targets 0.52.5", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -581,9 +581,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.7" version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@ -591,9 +591,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.5.7" version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@ -603,9 +603,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.5" version = "4.5.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
dependencies = [ dependencies = [
"heck 0.5.0", "heck 0.5.0",
"proc-macro2", "proc-macro2",
@ -745,17 +745,6 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "derivative"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]] [[package]]
name = "digest" name = "digest"
version = "0.10.7" version = "0.10.7"
@ -774,6 +763,18 @@ version = "0.15.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
[[package]]
name = "educe"
version = "0.5.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4bd92664bf78c4d3dba9b7cdafce6fa15b13ed3ed16175218196942e99168a8"
dependencies = [
"enum-ordinalize",
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]] [[package]]
name = "either" name = "either"
version = "1.11.0" version = "1.11.0"
@ -792,6 +793,26 @@ dependencies = [
"time", "time",
] ]
[[package]]
name = "enum-ordinalize"
version = "4.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fea0dcfa4e54eeb516fe454635a95753ddd39acda650ce703031c6973e315dd5"
dependencies = [
"enum-ordinalize-derive",
]
[[package]]
name = "enum-ordinalize-derive"
version = "4.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.60",
]
[[package]] [[package]]
name = "equivalent" name = "equivalent"
version = "1.0.1" version = "1.0.1"
@ -1523,13 +1544,14 @@ dependencies = [
[[package]] [[package]]
name = "mio" name = "mio"
version = "0.8.11" version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
dependencies = [ dependencies = [
"hermit-abi",
"libc", "libc",
"wasi", "wasi",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
@ -1616,16 +1638,6 @@ dependencies = [
"libm", "libm",
] ]
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
"hermit-abi",
"libc",
]
[[package]] [[package]]
name = "object" name = "object"
version = "0.32.2" version = "0.32.2"
@ -1712,7 +1724,7 @@ dependencies = [
"libc", "libc",
"redox_syscall 0.5.1", "redox_syscall 0.5.1",
"smallvec", "smallvec",
"windows-targets 0.52.5", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -2082,9 +2094,9 @@ dependencies = [
[[package]] [[package]]
name = "reqwest" name = "reqwest"
version = "0.12.5" version = "0.12.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" checksum = "f8f4955649ef5c38cc7f9e8aa41761d48fb9677197daea9984dc54f56aad5e63"
dependencies = [ dependencies = [
"base64 0.22.0", "base64 0.22.0",
"bytes", "bytes",
@ -2119,7 +2131,7 @@ dependencies = [
"wasm-bindgen-futures", "wasm-bindgen-futures",
"web-sys", "web-sys",
"webpki-roots 0.26.1", "webpki-roots 0.26.1",
"winreg", "windows-registry",
] ]
[[package]] [[package]]
@ -2403,9 +2415,9 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm" name = "sea-orm"
version = "0.12.15" 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 = "c8814e37dc25de54398ee62228323657520b7f29713b8e238649385dbe473ee0" checksum = "ea1fee0cf8528dbe6eda29d5798afc522a63b75e44c5b15721e6e64af9c7cc4b"
dependencies = [ dependencies = [
"async-stream", "async-stream",
"async-trait", "async-trait",
@ -2431,9 +2443,9 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm-cli" name = "sea-orm-cli"
version = "0.12.15" 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 = "620bc560062ae251b1366bde43b3f1508445cab5c2c8cbdb397034638ab1b357" checksum = "5f0b8869c75cf3fbb1bd860abb025033cd2e514c5f4fa43e792697cb1fe6c882"
dependencies = [ dependencies = [
"chrono", "chrono",
"clap", "clap",
@ -2448,9 +2460,9 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm-macros" name = "sea-orm-macros"
version = "0.12.15" 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 = "5e115c6b078e013aa963cc2d38c196c2c40b05f03d0ac872fe06b6e0d5265603" checksum = "8737b566799ed0444f278d13c300c4c6f1a91782f60ff5825a591852d5502030"
dependencies = [ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
@ -2462,9 +2474,9 @@ dependencies = [
[[package]] [[package]]
name = "sea-orm-migration" name = "sea-orm-migration"
version = "0.12.15" 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 = "ee8269bc6ff71afd6b78aa4333ac237a69eebd2cdb439036291e64fb4b8db23c" checksum = "216643749e26ce27ab6c51d3475f2692981d4a902d34455bcd322f412900df5c"
dependencies = [ dependencies = [
"async-trait", "async-trait",
"clap", "clap",
@ -2479,13 +2491,13 @@ dependencies = [
[[package]] [[package]]
name = "sea-query" name = "sea-query"
version = "0.30.7" version = "0.31.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4166a1e072292d46dc91f31617c2a1cdaf55a8be4b5c9f4bf2ba248e3ac4999b" checksum = "7e5073b2cfed767511a57d18115f3b3d8bcb5690bf8c89518caec6cb22c0cd74"
dependencies = [ dependencies = [
"bigdecimal", "bigdecimal",
"chrono", "chrono",
"derivative", "educe",
"inherent", "inherent",
"ordered-float", "ordered-float",
"rust_decimal", "rust_decimal",
@ -2497,9 +2509,9 @@ dependencies = [
[[package]] [[package]]
name = "sea-query-binder" name = "sea-query-binder"
version = "0.5.0" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36bbb68df92e820e4d5aeb17b4acd5cc8b5d18b2c36a4dd6f4626aabfa7ab1b9" checksum = "754965d4aee6145bec25d0898e5c931e6c22859789ce62fd85a42a15ed5a8ce3"
dependencies = [ dependencies = [
"bigdecimal", "bigdecimal",
"chrono", "chrono",
@ -2526,9 +2538,9 @@ dependencies = [
[[package]] [[package]]
name = "sea-schema" name = "sea-schema"
version = "0.14.2" version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30d148608012d25222442d1ebbfafd1228dbc5221baf4ec35596494e27a2394e" checksum = "ad52149fc81836ea7424c3425d8f6ed8ad448dd16d2e4f6a3907ba46f3f2fd78"
dependencies = [ dependencies = [
"futures", "futures",
"sea-query", "sea-query",
@ -2537,14 +2549,14 @@ dependencies = [
[[package]] [[package]]
name = "sea-schema-derive" name = "sea-schema-derive"
version = "0.2.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6f686050f76bffc4f635cda8aea6df5548666b830b52387e8bc7de11056d11e" checksum = "debdc8729c37fdbf88472f97fd470393089f997a909e535ff67c544d18cfccf0"
dependencies = [ dependencies = [
"heck 0.4.1", "heck 0.4.1",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 1.0.109", "syn 2.0.60",
] ]
[[package]] [[package]]
@ -2578,18 +2590,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.203" version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.203" version = "1.0.210"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2598,11 +2610,12 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.118" version = "1.0.128"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d947f6b3163d8857ea16c4fa0dd4840d52f3041039a85decd46867eb1abef2e4" checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr",
"ryu", "ryu",
"serde", "serde",
] ]
@ -2996,9 +3009,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "strum" name = "strum"
version = "0.25.0" version = "0.26.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290d54ea6f91c969195bdbcd7442c8c2a2ba87da8bf60a7ee86a235d4bc1e125" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
[[package]] [[package]]
name = "subtle" name = "subtle"
@ -3045,6 +3058,9 @@ name = "sync_wrapper"
version = "1.0.1" 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 = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394"
dependencies = [
"futures-core",
]
[[package]] [[package]]
name = "tap" name = "tap"
@ -3066,18 +3082,18 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.61" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.61" version = "1.0.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3142,28 +3158,27 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.38.0" version = "1.40.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
"libc", "libc",
"mio", "mio",
"num_cpus",
"parking_lot", "parking_lot",
"pin-project-lite", "pin-project-lite",
"signal-hook-registry", "signal-hook-registry",
"socket2 0.5.7", "socket2 0.5.7",
"tokio-macros", "tokio-macros",
"windows-sys 0.48.0", "windows-sys 0.52.0",
] ]
[[package]] [[package]]
name = "tokio-macros" name = "tokio-macros"
version = "2.3.0" version = "2.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -3601,7 +3616,37 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
dependencies = [ dependencies = [
"windows-targets 0.52.5", "windows-targets 0.52.6",
]
[[package]]
name = "windows-registry"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0"
dependencies = [
"windows-result",
"windows-strings",
"windows-targets 0.52.6",
]
[[package]]
name = "windows-result"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
dependencies = [
"windows-targets 0.52.6",
]
[[package]]
name = "windows-strings"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
dependencies = [
"windows-result",
"windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -3619,7 +3664,7 @@ version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [ dependencies = [
"windows-targets 0.52.5", "windows-targets 0.52.6",
] ]
[[package]] [[package]]
@ -3639,18 +3684,18 @@ dependencies = [
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm 0.52.5", "windows_aarch64_gnullvm 0.52.6",
"windows_aarch64_msvc 0.52.5", "windows_aarch64_msvc 0.52.6",
"windows_i686_gnu 0.52.5", "windows_i686_gnu 0.52.6",
"windows_i686_gnullvm", "windows_i686_gnullvm",
"windows_i686_msvc 0.52.5", "windows_i686_msvc 0.52.6",
"windows_x86_64_gnu 0.52.5", "windows_x86_64_gnu 0.52.6",
"windows_x86_64_gnullvm 0.52.5", "windows_x86_64_gnullvm 0.52.6",
"windows_x86_64_msvc 0.52.5", "windows_x86_64_msvc 0.52.6",
] ]
[[package]] [[package]]
@ -3661,9 +3706,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
@ -3673,9 +3718,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
@ -3685,15 +3730,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
[[package]] [[package]]
name = "windows_i686_gnullvm" name = "windows_i686_gnullvm"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
@ -3703,9 +3748,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
@ -3715,9 +3760,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
@ -3727,9 +3772,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
@ -3739,9 +3784,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.5" version = "0.52.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
@ -3761,16 +3806,6 @@ dependencies = [
"memchr", "memchr",
] ]
[[package]]
name = "winreg"
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5"
dependencies = [
"cfg-if",
"windows-sys 0.48.0",
]
[[package]] [[package]]
name = "wyz" name = "wyz"
version = "0.5.1" version = "0.5.1"

View File

@ -5,8 +5,8 @@ members = [
] ]
[workspace.dependencies] [workspace.dependencies]
sea-orm = "0.12.15" sea-orm = "1.0.1"
serde = "1.0.203" serde = "1.0.210"
time = "0.3.36" time = "0.3.36"
[workspace.package] [workspace.package]

121
README.md Normal file
View File

@ -0,0 +1,121 @@
# Alert-Me
[Alertswiss](https://www.alert.swiss/) is _an information hub collecting all
relevant information pertaining to precautions and behaviour during disasters
and emergencies in Switzerland._
The usual way of getting that information (the _alerts_) is via a proprietary
smartphone app and push notifications. While this works very well and is
perfectly fine for most, I think that such data is a nice stepping stone to
build upon.
Fortunately, the data is not hidden and easily accessible through a JSON
endpoint. In order to prepare this for consumption, the service in [app](./app/)
periodically polls the JSON data and persists alerts that changed or have not
been seen yet. Additionally it publishes all changes to an MQTT broker where
other clients can use that data as they see fit.
An example client is implemented for an
[nRF52840](https://www.nordicsemi.com/Products/nRF52840) microcontroller in
[display](./display/).
# Workspace Organization
## [app](./app/)
Backend service to poll alerts and publish new ones to an MQTT broker.
## [display](./display/)
Microcontroller ([nRF52840](https://www.nordicsemi.com/Products/nRF52840))
application to show basic alert information on an LCD. Because cargo has trouble
with different target architectures (see
[issue 9406](https://github.com/rust-lang/cargo/issues/9406)) this can not be
part of the workspace. Go into the directory to run build commands. There is a
separate [readme](./display/README.md) in its project directory.
## [entity](./entity/)
Entity definitions (_tables_) for [SeaORM](https://www.sea-ql.org/SeaORM/). This
translates the RDBMS entities to rust structs.
## [migration](./migration/)
Database migrations that get run at the start of the [alert-me app](./app/).
# Building
The recommended way is to use [nix](https://nixos.org/download/) with
[nix flakes](https://nixos.wiki/wiki/Flakes). It still is not for the faint of
heart but worth the investment.
Otherwise, [rustup](https://rustup.rs/) and other tools can be installed
manually.
## Nix
Install [nix](https://nixos.org/download/) and enable
[nix flakes](https://nixos.wiki/wiki/Flakes).
Enter the dev environment with `nix develop`. From there on the usual rust
commands work.
To build for different architectures use `nix-build .#cross-<architecture>` with
the desired architecture.
The following architectures are supported so far (different operating systems
would be nice but makes it more complicated):
- x86_64-linux
- i686-linux
- aarch64-linux
- armv6l-linux
The resulting binary (statically linked with [musl](https://musl.libc.org/)) is
written to `result/bin`.
## Manual Way
Install [rustup](https://rustup.rs/) and an MQTT broker (such as
[mosquitto](https://mosquitto.org/)). When running rust commands (such as
`cargo build`), rustup should pull in the specified toolchain. However, I can
not test this.
# Usage
During development the typical way is to run `cargo run -p alert-me --`,
followed by the cli arguments. Nothing changes if instead one runs an already
built binary directly (such as `result/bin/alert-me`) apart from that first
part.
```
Usage: alert-me [OPTIONS] --mqtt-broker <MQTT_BROKER> --mqtt-user <MQTT_USER> --mqtt-password <MQTT_PASSWORD>
Options:
-i, --interval <INTERVAL> Update interval in seconds [default: 10]
-c, --connection <CONNECTION> Database connection string where timestamps are stored (SQLite, Postgres or MySql) [default: sqlite::memory:]
-m, --mqtt-broker <MQTT_BROKER> MQTT broker where alerts get published
-p, --mqtt-port <MQTT_PORT> MQTT port [default: 1883]
-u, --mqtt-user <MQTT_USER> MQTT user
-P, --mqtt-password <MQTT_PASSWORD> MQTT password
-h, --help Print help
-V, --version Print version
```
## MQTT Broker
The alert-me app needs to connect to an MQTT broker to publish alerts. The
following is an example of running your own with
[mosquitto](https://mosquitto.org/)).
Create a file `mosquitto.conf` with a content of:
```
```
A password for publishing is set, so not everyone can just publish alerts. This
is not mandatory though.
Run the broker with `mosquitto -v -c mosquitto.conf`. With
`mosquitto_sub -v -h localhost -p 1883 -t 'alerts'` new alerts will be shown as
they arrive.

View File

@ -10,17 +10,17 @@ repository = { workspace = true }
entity = { path = "../entity" } entity = { path = "../entity" }
migration = { path = "../migration" } migration = { path = "../migration" }
ciborium = "0.2.2" ciborium = "0.2.2"
clap = { version = "4.5.7", features = ["derive"] } clap = { version = "4.5.18", features = ["derive"] }
config = { version = "0.14.0", default-features = false, features = [ "toml" ] } config = { version = "0.14.0", default-features = false, features = [ "toml" ] }
futures = "0.3.30" futures = "0.3.30"
itertools = "0.13.0" itertools = "0.13.0"
reqwest = { version = "0.12.5", features = ["json", "rustls-tls"], default-features = false } reqwest = { version = "0.12.7", features = ["json", "rustls-tls"], default-features = false }
rumqttc = "0.24.0" rumqttc = "0.24.0"
sea-orm = { workspace = true, features = [ "with-time", "sqlx-sqlite", "sqlx-postgres", "sqlx-mysql", "runtime-tokio-rustls", "macros" ] } sea-orm = { workspace = true, features = [ "with-time", "sqlx-sqlite", "sqlx-postgres", "sqlx-mysql", "runtime-tokio-rustls", "macros" ] }
serde = { workspace = true } serde = { workspace = true }
serde_json = "1.0.118" serde_json = "1.0.128"
thiserror = "1.0.61" thiserror = "1.0.64"
time = { workspace = true, features = ["macros", "serde", "formatting", "parsing" ] } time = { workspace = true, features = ["macros", "serde", "formatting", "parsing" ] }
tokio = { version = "1.38.0", features = ["full"] } tokio = { version = "1.40.0", features = ["full"] }
tracing = "0.1.40" tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }

View File

@ -1,7 +1,9 @@
use crate::json::alerts::Alerts; use crate::json::alerts::Alerts;
// TODO: maybe make this overridable?
const ALERT_SWISS_URL: &str = "https://www.alert.swiss/content/alertswiss-internet/en/home/_jcr_content/polyalert.alertswiss_alerts.actual.json"; const ALERT_SWISS_URL: &str = "https://www.alert.swiss/content/alertswiss-internet/en/home/_jcr_content/polyalert.alertswiss_alerts.actual.json";
/// Fetch alert information from alertswiss as a json document.
pub async fn fetch_alerts() -> Result<Alerts, reqwest::Error> { pub async fn fetch_alerts() -> Result<Alerts, reqwest::Error> {
reqwest::get(ALERT_SWISS_URL).await?.json::<Alerts>().await reqwest::get(ALERT_SWISS_URL).await?.json::<Alerts>().await
} }

View File

@ -9,6 +9,7 @@ pub struct Cli {
/// Update interval in seconds /// Update interval in seconds
#[arg(short, long, default_value_t = 10)] #[arg(short, long, default_value_t = 10)]
pub interval: u64, pub interval: u64,
/// Database connection string where timestamps are stored (SQLite, Postgres or MySql) /// Database connection string where timestamps are stored (SQLite, Postgres or MySql)
#[arg(short, long, default_value_t = format!("sqlite::memory:"))] #[arg(short, long, default_value_t = format!("sqlite::memory:"))]
pub connection: String, pub connection: String,

View File

@ -1,16 +1,30 @@
//! Provide functionality to interact with a relational database
//! for storing and retrieving alert information.
use entity::alerts; use entity::alerts;
use migration::{Migrator, MigratorTrait}; use migration::{Migrator, MigratorTrait};
use sea_orm::{ActiveModelTrait, Database, DatabaseConnection, DbErr, EntityTrait, Set}; use sea_orm::{ActiveModelTrait, DatabaseConnection, EntityTrait, Set};
use thiserror::Error;
use tracing::debug; use tracing::debug;
use crate::json::alert::Alert; use crate::json::alert::Alert;
#[derive(Error, Debug)]
#[error("rdbms error")]
pub enum RdbmsError {
/// Database Error
#[error("db error")]
DbError(#[from] sea_orm::DbErr),
}
/// Wrap a database connection and allow operations on it.
pub struct Db { pub struct Db {
connection: DatabaseConnection, connection: DatabaseConnection,
} }
impl Db { impl Db {
pub async fn is_alert_updated(&self, alert: &Alert) -> Result<bool, DbErr> { /// Check if an alert has been updated in the database.
pub async fn is_alert_updated(&self, alert: &Alert) -> Result<bool, RdbmsError> {
let db_alert = entity::alerts::Entity::find_by_id(&alert.identifier) let db_alert = entity::alerts::Entity::find_by_id(&alert.identifier)
.one(&self.connection) .one(&self.connection)
.await?; .await?;
@ -21,7 +35,8 @@ impl Db {
}) })
} }
pub async fn save_alert(&self, alert: &Alert) -> Result<(), DbErr> { /// Save an alert to the database.
pub async fn save_alert(&self, alert: &Alert) -> Result<(), RdbmsError> {
let db_alert = entity::alerts::Entity::find_by_id(&alert.identifier) let db_alert = entity::alerts::Entity::find_by_id(&alert.identifier)
.one(&self.connection) .one(&self.connection)
.await?; .await?;
@ -40,11 +55,15 @@ impl Db {
} }
} }
pub async fn connect(connection_string: &str) -> Result<Db, DbErr> { /// Establish a connection to a database.
///
/// Run all migrations.
pub async fn connect(connection_string: &str) -> Result<Db, RdbmsError> {
debug!("connecting to {connection_string}..."); debug!("connecting to {connection_string}...");
let connection: DatabaseConnection = Database::connect(connection_string).await?; let connection = migration::sea_orm::Database::connect(connection_string).await?;
Migrator::up(&connection, None).await?; Migrator::up(&connection, None).await?;
let connection = sea_orm::Database::connect(connection_string).await?;
Ok(Db { connection }) Ok(Db { connection })
} }

View File

@ -1,12 +1,12 @@
use sea_orm::DbErr; use crate::datastore::rdbms::RdbmsError;
use thiserror::Error; use thiserror::Error;
#[derive(Error, Debug)] #[derive(Error, Debug)]
#[error("opds error")] #[error("application error")]
pub enum Error { pub enum Error {
/// Database Error /// Database Error
#[error("opds error")] #[error("database error")]
DbError(#[from] DbErr), DbError(#[from] RdbmsError),
/// Error fetching data from alertswiss /// Error fetching data from alertswiss
#[error("data error")] #[error("data error")]
FetchError(#[from] reqwest::Error), FetchError(#[from] reqwest::Error),

View File

@ -48,6 +48,9 @@ mod json {
pub mod logging; pub mod logging;
pub mod mqtt; pub mod mqtt;
/// Check for new alerts, save them into the local database and publish them to mqtt.
///
/// Return new alerts.
async fn handle_alerts(db: &Db) -> Result<Vec<Alert>, Error> { async fn handle_alerts(db: &Db) -> Result<Vec<Alert>, Error> {
info!("checking alerts"); info!("checking alerts");
@ -56,8 +59,10 @@ async fn handle_alerts(db: &Db) -> Result<Vec<Alert>, Error> {
.list .list
.into_iter() .into_iter()
.filter(|alert| !alert.identifier.starts_with("TEST-")) .filter(|alert| !alert.identifier.starts_with("TEST-"))
// we do not need the test alerts
.collect(); .collect();
// filter for new alerts by checking with the database
let new_alerts: Vec<Alert> = stream::iter(alerts) let new_alerts: Vec<Alert> = stream::iter(alerts)
.filter_map(|alert| async move { .filter_map(|alert| async move {
if db.is_alert_updated(&alert).await.ok().unwrap_or(false) { if db.is_alert_updated(&alert).await.ok().unwrap_or(false) {
@ -69,6 +74,7 @@ async fn handle_alerts(db: &Db) -> Result<Vec<Alert>, Error> {
.collect() .collect()
.await; .await;
// persist new alerts
stream::iter(new_alerts.clone()) stream::iter(new_alerts.clone())
.for_each_concurrent(None, |alert| async move { .for_each_concurrent(None, |alert| async move {
info!("saving alert {}", alert.identifier); info!("saving alert {}", alert.identifier);
@ -81,6 +87,7 @@ async fn handle_alerts(db: &Db) -> Result<Vec<Alert>, Error> {
Ok(new_alerts) Ok(new_alerts)
} }
/// Entry point to run the alert-me application.
pub async fn run(config: Config) -> Result<(), Error> { pub async fn run(config: Config) -> Result<(), Error> {
let mut interval = time::interval(Duration::from_secs(config.interval)); let mut interval = time::interval(Duration::from_secs(config.interval));

View File

@ -1,3 +1,5 @@
//! MQTT publishing.
use rumqttc::{AsyncClient, EventLoop, MqttOptions, QoS}; use rumqttc::{AsyncClient, EventLoop, MqttOptions, QoS};
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tokio::sync::Mutex; use tokio::sync::Mutex;
@ -5,6 +7,7 @@ use tracing::debug;
use crate::{config::MqttConfig, error::Error}; use crate::{config::MqttConfig, error::Error};
/// Encapsulate the MQTT eventloop for publishing data.
pub struct Mqtt { pub struct Mqtt {
client: AsyncClient, client: AsyncClient,
eventloop: Arc<Mutex<EventLoop>>, eventloop: Arc<Mutex<EventLoop>>,
@ -12,6 +15,7 @@ pub struct Mqtt {
} }
impl Mqtt { impl Mqtt {
/// Run the MQTT event loop to properly receive messages.
async fn run_event_loop(&self) { async fn run_event_loop(&self) {
let mut event_loop_running = self.event_loop_running.lock().await; let mut event_loop_running = self.event_loop_running.lock().await;
if !*event_loop_running { if !*event_loop_running {
@ -28,6 +32,7 @@ impl Mqtt {
} }
} }
/// Publish data to an MQTT topic with QoS `AtLeastOnce`..
pub async fn publish(&self, payload: &[u8]) -> Result<(), Error> { pub async fn publish(&self, payload: &[u8]) -> Result<(), Error> {
self.run_event_loop().await; self.run_event_loop().await;
self.client self.client
@ -38,6 +43,7 @@ impl Mqtt {
} }
} }
/// Connect and authenticate to an MQTT broker.
pub fn connect(config: &MqttConfig) -> Mqtt { pub fn connect(config: &MqttConfig) -> Mqtt {
let mut options = MqttOptions::new("rumqtt-async", config.broker.clone(), config.port); let mut options = MqttOptions::new("rumqtt-async", config.broker.clone(), config.port);
let options = options let options = options

1047
display/Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -5,26 +5,26 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies.embassy-nrf] [dependencies.embassy-nrf]
version = "0.1.0" version = "0.2.0"
git = "https://github.com/embassy-rs/embassy.git" git = "https://github.com/embassy-rs/embassy.git"
rev = "cf0d227cca92a80e85575154d380d1ff73fb32cf" rev = "0ede8479dc4c6a58cfab0a5d4df41c0592405971"
features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"] features = ["defmt", "nrf52840", "time-driver-rtc1", "gpiote", "unstable-pac", "time"]
[dependencies.embassy-embedded-hal] [dependencies.embassy-embedded-hal]
version = "0.1.0" version = "0.2.0"
git = "https://github.com/embassy-rs/embassy.git" git = "https://github.com/embassy-rs/embassy.git"
rev = "cf0d227cca92a80e85575154d380d1ff73fb32cf" rev = "0ede8479dc4c6a58cfab0a5d4df41c0592405971"
[dependencies.embassy-executor] [dependencies.embassy-executor]
version = "0.5.0" version = "0.6.0"
git = "https://github.com/embassy-rs/embassy.git" git = "https://github.com/embassy-rs/embassy.git"
rev = "cf0d227cca92a80e85575154d380d1ff73fb32cf" rev = "0ede8479dc4c6a58cfab0a5d4df41c0592405971"
features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"] features = ["task-arena-size-32768", "arch-cortex-m", "executor-thread", "executor-interrupt", "defmt", "integrated-timers"]
[dependencies.embassy-time] [dependencies.embassy-time]
version = "0.3.0" version = "0.3.2"
git = "https://github.com/embassy-rs/embassy.git" git = "https://github.com/embassy-rs/embassy.git"
rev = "cf0d227cca92a80e85575154d380d1ff73fb32cf" rev = "0ede8479dc4c6a58cfab0a5d4df41c0592405971"
features = ["defmt", "defmt-timestamp-uptime"] features = ["defmt", "defmt-timestamp-uptime"]
[dependencies.embassy-sync] [dependencies.embassy-sync]
@ -35,7 +35,7 @@ rev = "cf0d227cca92a80e85575154d380d1ff73fb32cf"
[dependencies.nrf-softdevice] [dependencies.nrf-softdevice]
version = "0.1.0" version = "0.1.0"
git = "https://github.com/embassy-rs/nrf-softdevice.git" git = "https://github.com/embassy-rs/nrf-softdevice.git"
rev = "3c53b8c454cc9331082053033485e713abcadbb5" rev = "991d28e3c61687908acc53e748191eb59d00e27a"
features = ["defmt", "ble-peripheral", "ble-central", "critical-section-impl", "ble-gatt-server", "nrf52840", "s140"] features = ["defmt", "ble-peripheral", "ble-central", "critical-section-impl", "ble-gatt-server", "nrf52840", "s140"]
[dependencies] [dependencies]

View File

@ -74,7 +74,7 @@
with fenix.packages.${system}; with fenix.packages.${system};
fromToolchainFile { fromToolchainFile {
file = ./rust-toolchain.toml; file = ./rust-toolchain.toml;
sha256 = "sha256-efF87P7mtVVzZ6KRvRYLKOk4KrDcCuA0Kv9luRrjBzI="; sha256 = "sha256-VZZnlyP69+Y3crrLHQyJirqlHrTtGTsyiSnZB8jEvVo=";
}; };
in in
with pkgs; with pkgs;

View File

@ -15,10 +15,10 @@ path = "src/lib.rs"
async-std = { version = "1", features = ["attributes", "tokio1"] } async-std = { version = "1", features = ["attributes", "tokio1"] }
[dependencies.sea-orm-migration] [dependencies.sea-orm-migration]
version = "0.12.0" version = "1.0.1"
features = [ features = [
# Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI. # Enable at least one `ASYNC_RUNTIME` and `DATABASE_DRIVER` feature if you want to run migration via CLI.
# View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime. # View the list of supported features at https://www.sea-ql.org/SeaORM/docs/install-and-config/database-and-async-runtime.
# e.g. # e.g.
"runtime-tokio-rustls", "sqlx-postgres", "runtime-tokio-rustls", "sqlx-sqlite", "sqlx-postgres", "sqlx-mysql"
] ]

View File

@ -1,5 +1,5 @@
[toolchain] [toolchain]
channel = "nightly" channel = "stable"
components = [ "clippy", "rustfmt" ] components = [ "clippy", "rustfmt" ]
targets = [ "thumbv7em-none-eabi", "thumbv7em-none-eabihf" ] targets = [ "thumbv7em-none-eabi", "thumbv7em-none-eabihf" ]
profile = "minimal" profile = "minimal"