Cleanup and organize code into modules
This commit is contained in:
parent
827a519ca5
commit
10d48a91c3
15 changed files with 509 additions and 171 deletions
236
Cargo.lock
generated
236
Cargo.lock
generated
|
@ -60,6 +60,7 @@ dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
|
"headers",
|
||||||
"http",
|
"http",
|
||||||
"http-body",
|
"http-body",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
@ -113,6 +114,12 @@ dependencies = [
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.21.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "1.3.2"
|
||||||
|
@ -125,6 +132,15 @@ version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bytes"
|
name = "bytes"
|
||||||
version = "1.5.0"
|
version = "1.5.0"
|
||||||
|
@ -146,6 +162,44 @@ 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 = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cpufeatures"
|
||||||
|
version = "0.2.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-channel"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.8.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deadpool"
|
name = "deadpool"
|
||||||
version = "0.10.0"
|
version = "0.10.0"
|
||||||
|
@ -241,12 +295,34 @@ dependencies = [
|
||||||
"syn 2.0.39",
|
"syn 2.0.39",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "equivalent"
|
||||||
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 = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.22"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall 0.3.5",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fnv"
|
name = "fnv"
|
||||||
version = "1.0.7"
|
version = "1.0.7"
|
||||||
|
@ -262,6 +338,15 @@ dependencies = [
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsevent-sys"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-channel"
|
name = "futures-channel"
|
||||||
version = "0.3.29"
|
version = "0.3.29"
|
||||||
|
@ -301,6 +386,16 @@ dependencies = [
|
||||||
"pin-utils",
|
"pin-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "gimli"
|
name = "gimli"
|
||||||
version = "0.28.0"
|
version = "0.28.0"
|
||||||
|
@ -313,6 +408,30 @@ version = "0.14.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers"
|
||||||
|
version = "0.3.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"bytes",
|
||||||
|
"headers-core",
|
||||||
|
"http",
|
||||||
|
"httpdate",
|
||||||
|
"mime",
|
||||||
|
"sha1",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "headers-core"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
|
||||||
|
dependencies = [
|
||||||
|
"http",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hermit-abi"
|
name = "hermit-abi"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -392,12 +511,52 @@ dependencies = [
|
||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify"
|
||||||
|
version = "0.9.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"inotify-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify-sys"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itoa"
|
name = "itoa"
|
||||||
version = "1.0.9"
|
version = "1.0.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
|
||||||
|
dependencies = [
|
||||||
|
"kqueue-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue-sys"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lazy_static"
|
name = "lazy_static"
|
||||||
version = "1.4.0"
|
version = "1.4.0"
|
||||||
|
@ -447,6 +606,7 @@ dependencies = [
|
||||||
"diesel",
|
"diesel",
|
||||||
"diesel_migrations",
|
"diesel_migrations",
|
||||||
"maud",
|
"maud",
|
||||||
|
"notify",
|
||||||
"serde",
|
"serde",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tower-http",
|
"tower-http",
|
||||||
|
@ -551,10 +711,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
checksum = "3dce281c5e46beae905d4de1870d8b1509a9142b62eedf18b443b011ca8343d0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys",
|
"windows-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify"
|
||||||
|
version = "6.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.4.1",
|
||||||
|
"crossbeam-channel",
|
||||||
|
"filetime",
|
||||||
|
"fsevent-sys",
|
||||||
|
"inotify",
|
||||||
|
"kqueue",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"mio",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu-ansi-term"
|
name = "nu-ansi-term"
|
||||||
version = "0.46.0"
|
version = "0.46.0"
|
||||||
|
@ -614,7 +794,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"libc",
|
"libc",
|
||||||
"redox_syscall",
|
"redox_syscall 0.4.1",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"windows-targets",
|
"windows-targets",
|
||||||
]
|
]
|
||||||
|
@ -711,6 +891,15 @@ dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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"
|
||||||
|
@ -782,6 +971,15 @@ version = "1.0.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -850,6 +1048,17 @@ dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha1"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.7"
|
version = "0.1.7"
|
||||||
|
@ -1173,6 +1382,12 @@ version = "0.2.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typenum"
|
||||||
|
version = "1.17.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicase"
|
name = "unicase"
|
||||||
version = "2.7.0"
|
version = "2.7.0"
|
||||||
|
@ -1206,6 +1421,16 @@ version = "0.9.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "want"
|
name = "want"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
|
@ -1237,6 +1462,15 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596"
|
||||||
|
dependencies = [
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi-x86_64-pc-windows-gnu"
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
|
|
@ -5,12 +5,13 @@ edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.75"
|
anyhow = "1.0.75"
|
||||||
axum = "0.6.20"
|
axum = { version = "0.6.20", features = ["headers"] }
|
||||||
deadpool = "0.10.0"
|
deadpool = "0.10.0"
|
||||||
deadpool-diesel = { version = "0.5.0", features = ["rt_tokio_1", "sqlite", "tracing", "serde"] }
|
deadpool-diesel = { version = "0.5.0", features = ["rt_tokio_1", "sqlite", "tracing", "serde"] }
|
||||||
diesel = { version = "2.1.3", features = ["sqlite"] }
|
diesel = { version = "2.1.3", features = ["sqlite"] }
|
||||||
diesel_migrations = { version = "2.1.0", features = ["sqlite"] }
|
diesel_migrations = { version = "2.1.0", features = ["sqlite"] }
|
||||||
maud = "0.25.0"
|
maud = "0.25.0"
|
||||||
|
notify = "6.1.1"
|
||||||
serde = { version = "1.0.192", features = ["derive"] }
|
serde = { version = "1.0.192", features = ["derive"] }
|
||||||
tokio = { version = "1.34.0", features = ["full", "macros", "rt-multi-thread"] }
|
tokio = { version = "1.34.0", features = ["full", "macros", "rt-multi-thread"] }
|
||||||
tower-http = { version = "0.4.4", features = ["fs"] }
|
tower-http = { version = "0.4.4", features = ["fs"] }
|
||||||
|
|
|
@ -43,6 +43,9 @@
|
||||||
devShell = with pkgs;
|
devShell = with pkgs;
|
||||||
mkShell {
|
mkShell {
|
||||||
buildInputs = [
|
buildInputs = [
|
||||||
|
# dedupe from package inputs?
|
||||||
|
sqlite
|
||||||
|
|
||||||
toolchain
|
toolchain
|
||||||
|
|
||||||
rustfmt
|
rustfmt
|
||||||
|
@ -50,8 +53,6 @@
|
||||||
rust-analyzer
|
rust-analyzer
|
||||||
nodePackages_latest.vscode-langservers-extracted
|
nodePackages_latest.vscode-langservers-extracted
|
||||||
|
|
||||||
# dedupe from package inputs?
|
|
||||||
sqlite
|
|
||||||
diesel-cli
|
diesel-cli
|
||||||
hurl
|
hurl
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
create table users (
|
create table users (
|
||||||
id text primary key,
|
id text primary key,
|
||||||
name text,
|
name text,
|
||||||
hashed_password text
|
hashed_password binary
|
||||||
)
|
)
|
||||||
|
|
7
src/app.rs
Normal file
7
src/app.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use crate::{instrumentation, router, server::listen};
|
||||||
|
|
||||||
|
pub async fn run() -> Result<(), anyhow::Error> {
|
||||||
|
instrumentation::setup_trace_logger();
|
||||||
|
listen(router::new().await?).await;
|
||||||
|
Ok(())
|
||||||
|
}
|
41
src/database.rs
Normal file
41
src/database.rs
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
use deadpool_diesel::sqlite::{Manager, Pool, Runtime};
|
||||||
|
use diesel::sqlite::Sqlite;
|
||||||
|
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
pub struct Database {
|
||||||
|
pub pool: Pool,
|
||||||
|
}
|
||||||
|
|
||||||
|
const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
||||||
|
|
||||||
|
impl Database {
|
||||||
|
// TODO: database seeding?
|
||||||
|
|
||||||
|
fn run_migrations(
|
||||||
|
connection: &mut impl MigrationHarness<Sqlite>,
|
||||||
|
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
|
||||||
|
// This will run the necessary migrations.
|
||||||
|
//
|
||||||
|
// See the documentation for `MigrationHarness` for
|
||||||
|
// all available methods.
|
||||||
|
connection.run_pending_migrations(MIGRATIONS)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make an actual error type
|
||||||
|
pub async fn new<T: AsRef<str>>(database_url: T) -> Result<Self, anyhow::Error> {
|
||||||
|
let manager = Manager::new(database_url.as_ref(), Runtime::Tokio1);
|
||||||
|
let pool = Pool::builder(manager).max_size(8).build().unwrap();
|
||||||
|
|
||||||
|
let conn = pool.get().await?;
|
||||||
|
let _ = conn
|
||||||
|
.interact(|c| Self::run_migrations(c))
|
||||||
|
.await
|
||||||
|
.expect("Failed to run migrations");
|
||||||
|
info!("Migrations completed!");
|
||||||
|
|
||||||
|
return Ok(Database { pool });
|
||||||
|
}
|
||||||
|
}
|
8
src/feather_icons.rs
Normal file
8
src/feather_icons.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
// TODO: perhaps just download all feather icons and include lazily or something?
|
||||||
|
// feather icons
|
||||||
|
pub const FEATHER_ICON_USER_PLUS: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-user-plus"><path d="M16 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"></path><circle cx="8.5" cy="7" r="4"></circle><line x1="20" y1="8" x2="20" y2="14"></line><line x1="23" y1="11" x2="17" y2="11"></line></svg>"#;
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
|
pub const FEATHER_ICON_LAYOUT: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layout"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>"#;
|
||||||
|
|
||||||
|
pub const FEATHER_ICON_LOGIN: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-log-in"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" y1="12" x2="3" y2="12"></line></svg>"#;
|
13
src/instrumentation.rs
Normal file
13
src/instrumentation.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use tracing::{instrument, trace};
|
||||||
|
use tracing_subscriber::{filter::LevelFilter, EnvFilter};
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub fn setup_trace_logger() {
|
||||||
|
let filter = EnvFilter::builder()
|
||||||
|
.with_default_directive(LevelFilter::INFO.into())
|
||||||
|
.parse_lossy("info,lyrs=trace");
|
||||||
|
|
||||||
|
tracing_subscriber::fmt().with_env_filter(filter).init();
|
||||||
|
|
||||||
|
trace!("Starting...");
|
||||||
|
}
|
178
src/main.rs
178
src/main.rs
|
@ -1,172 +1,20 @@
|
||||||
//! lyrs entrypoint
|
//! lyrs entrypoint
|
||||||
|
|
||||||
use axum::{http::StatusCode, response::Html, routing::get, Router};
|
// TODO: Break this module up
|
||||||
use deadpool_diesel::sqlite::{Manager, Pool, Runtime};
|
// TODO: Implement authn
|
||||||
use diesel::sqlite::Sqlite;
|
|
||||||
use diesel_migrations::{embed_migrations, EmbeddedMigrations, MigrationHarness};
|
|
||||||
use maud::{html, PreEscaped};
|
|
||||||
use std::{env, net::SocketAddr};
|
|
||||||
use tower_http::services::ServeDir;
|
|
||||||
use tower_livereload::LiveReloadLayer;
|
|
||||||
use tracing::{info, instrument, span, trace, Level};
|
|
||||||
use tracing_subscriber::{filter::LevelFilter, EnvFilter};
|
|
||||||
|
|
||||||
#[instrument]
|
mod app;
|
||||||
fn setup_trace_logger() {
|
mod database;
|
||||||
let filter = EnvFilter::builder()
|
mod feather_icons;
|
||||||
.with_default_directive(LevelFilter::INFO.into())
|
mod instrumentation;
|
||||||
.parse_lossy("info,lyrs=trace");
|
mod partials;
|
||||||
|
mod router;
|
||||||
tracing_subscriber::fmt().with_env_filter(filter).init();
|
mod schema;
|
||||||
|
mod server;
|
||||||
trace!("Starting...");
|
mod state;
|
||||||
}
|
mod views;
|
||||||
|
|
||||||
// struct State {
|
|
||||||
// pub pool: Pool,
|
|
||||||
// }
|
|
||||||
|
|
||||||
fn run_migrations(
|
|
||||||
connection: &mut impl MigrationHarness<Sqlite>,
|
|
||||||
) -> Result<(), Box<dyn std::error::Error + Send + Sync + 'static>> {
|
|
||||||
// This will run the necessary migrations.
|
|
||||||
//
|
|
||||||
// See the documentation for `MigrationHarness` for
|
|
||||||
// all available methods.
|
|
||||||
connection.run_pending_migrations(MIGRATIONS)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument]
|
|
||||||
async fn router() -> Result<Router, anyhow::Error> {
|
|
||||||
let app_router = Router::new()
|
|
||||||
.route("/hello-world", get(greet_world))
|
|
||||||
.route("/hello-world-text", get(greet_world_text));
|
|
||||||
|
|
||||||
let assets_dir = ServeDir::new("./assets");
|
|
||||||
|
|
||||||
let pool;
|
|
||||||
|
|
||||||
let dbspan = span!(Level::WARN, "database_setup");
|
|
||||||
{
|
|
||||||
let _s = dbspan.enter();
|
|
||||||
|
|
||||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
|
||||||
let manager = Manager::new(database_url, Runtime::Tokio1);
|
|
||||||
pool = Pool::builder(manager).max_size(8).build().unwrap();
|
|
||||||
info!("Database pool creation complete!");
|
|
||||||
|
|
||||||
let conn = pool.get().await?;
|
|
||||||
let mspan = span!(Level::INFO, "migrations");
|
|
||||||
{
|
|
||||||
let _s = mspan.enter();
|
|
||||||
let _ = conn
|
|
||||||
.interact(|c| run_migrations(c))
|
|
||||||
.await
|
|
||||||
.expect("Failed to run migrations");
|
|
||||||
info!("Migrations completed!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// let state = Arc::new(State { pool });
|
|
||||||
|
|
||||||
Ok(Router::new()
|
|
||||||
.fallback(|| async { (StatusCode::NOT_FOUND, "404 page not found") })
|
|
||||||
.nest("/app", app_router)
|
|
||||||
.nest_service("/assets", assets_dir)
|
|
||||||
.route("/", get(index))
|
|
||||||
.layer(LiveReloadLayer::new()))
|
|
||||||
// .with_state(state))
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn listen(r: Router) {
|
|
||||||
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
|
||||||
info!("Listening on '{}'", addr);
|
|
||||||
axum::Server::bind(&addr)
|
|
||||||
.serve(r.into_make_service())
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!();
|
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), anyhow::Error> {
|
async fn main() -> Result<(), anyhow::Error> {
|
||||||
setup_trace_logger();
|
app::run().await
|
||||||
listen(router().await?).await;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
// feather icons
|
|
||||||
const FEATHER_ICON_LAYOUT: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-layout"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><line x1="3" y1="9" x2="21" y2="9"></line><line x1="9" y1="21" x2="9" y2="9"></line></svg>"#;
|
|
||||||
|
|
||||||
const FEATHER_ICON_LOGIN: &str = r#"<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-log-in"><path d="M15 3h4a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2h-4"></path><polyline points="10 17 15 12 10 7"></polyline><line x1="15" y1="12" x2="3" y2="12"></line></svg>"#;
|
|
||||||
|
|
||||||
#[instrument]
|
|
||||||
async fn index() -> Html<String> {
|
|
||||||
Html(
|
|
||||||
html! {
|
|
||||||
head {
|
|
||||||
link rel="stylesheet" href="/assets/styles.css" {}
|
|
||||||
link rel="icon" href="/assets/favicon.svg" {}
|
|
||||||
}
|
|
||||||
header class="flex" {
|
|
||||||
nav class="flex" {
|
|
||||||
h1 {
|
|
||||||
a href="/" { "lyrs" }
|
|
||||||
}
|
|
||||||
// ul class="flex"
|
|
||||||
// {
|
|
||||||
// a href="/login" { "Login" }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
nav class="flex" {
|
|
||||||
ul class="flex"
|
|
||||||
{
|
|
||||||
a href="/dashboard" {
|
|
||||||
(PreEscaped(FEATHER_ICON_LAYOUT))
|
|
||||||
"Dashboard"
|
|
||||||
}
|
|
||||||
a href="/login" {
|
|
||||||
(PreEscaped(FEATHER_ICON_LOGIN))
|
|
||||||
"Login"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
main class="prose" {
|
|
||||||
h1 { "Manage live lyrics and music displays" }
|
|
||||||
p { "Stop struggling to share the same messy set of PowerPoint files or Google Presentations. Make editing and controlling your live lyrics and music displays easy and simple." }
|
|
||||||
ul {
|
|
||||||
li { "Live collaboration with your team" }
|
|
||||||
li { "Fully compatible with any device" }
|
|
||||||
li { "Simple workflow" }
|
|
||||||
li { "Dark theme and light theme" }
|
|
||||||
li { "Generous free plan" }
|
|
||||||
li { "Lightweight and fast" }
|
|
||||||
}
|
|
||||||
section class="flex gap" {
|
|
||||||
a class="button bg-primary" href="/register/anonymous" { "Try now" }
|
|
||||||
a class="button" href="/login" { "Login" }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.into_string(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument]
|
|
||||||
async fn greet_world() -> Html<String> {
|
|
||||||
Html(
|
|
||||||
html! {
|
|
||||||
h1 { (greet_world_text().await) }
|
|
||||||
}
|
|
||||||
.into_string(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[instrument]
|
|
||||||
async fn greet_world_text() -> &'static str {
|
|
||||||
"Hello, World!"
|
|
||||||
}
|
}
|
||||||
|
|
51
src/partials.rs
Normal file
51
src/partials.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use maud::{html, Markup, PreEscaped};
|
||||||
|
|
||||||
|
use crate::feather_icons;
|
||||||
|
|
||||||
|
pub fn header() -> Markup {
|
||||||
|
html! {
|
||||||
|
head {
|
||||||
|
link rel="stylesheet" href="/assets/styles.css" {}
|
||||||
|
link rel="icon" href="/assets/favicon.svg" {}
|
||||||
|
}
|
||||||
|
body hx-ext="preload" {
|
||||||
|
header class="flex" {
|
||||||
|
nav class="flex" {
|
||||||
|
h1 {
|
||||||
|
a href="/" { "lyrs" }
|
||||||
|
}
|
||||||
|
// ul class="flex"
|
||||||
|
// {
|
||||||
|
// a href="/login" { "Login" }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
nav class="flex" {
|
||||||
|
ul class="flex"
|
||||||
|
{
|
||||||
|
// a href="/dashboard" {
|
||||||
|
// (PreEscaped(FEATHER_ICON_LAYOUT))
|
||||||
|
// "Dashboard"
|
||||||
|
// }
|
||||||
|
a href="/register" preload="" {
|
||||||
|
(PreEscaped(feather_icons::FEATHER_ICON_USER_PLUS))
|
||||||
|
"Register"
|
||||||
|
}
|
||||||
|
a href="/login" preload="" {
|
||||||
|
(PreEscaped(feather_icons::FEATHER_ICON_LOGIN))
|
||||||
|
"Login"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn footer() -> Markup {
|
||||||
|
html! {
|
||||||
|
footer {
|
||||||
|
script src="https://unpkg.com/htmx.org@1.9.8" crossorigin="anonymous" integrity="sha384-rgjA7mptc2ETQqXoYC3/zJvkU7K/aP44Y+z7xQuJiVnB/422P/Ak+F/AqFR7E4Wr" {}
|
||||||
|
script src="https://unpkg.com/htmx.org@1.9.8/dist/ext/preload.js" crossorigin="anonymous" {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
36
src/router.rs
Normal file
36
src/router.rs
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
use std::{path::Path, sync::Arc};
|
||||||
|
|
||||||
|
use axum::{http::StatusCode, routing::get, Router};
|
||||||
|
use notify::Watcher;
|
||||||
|
use tower_http::services::ServeDir;
|
||||||
|
use tower_livereload::LiveReloadLayer;
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use crate::{state::State, views};
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub async fn new() -> Result<Router, anyhow::Error> {
|
||||||
|
let app_router = Router::new()
|
||||||
|
.route("/hello-world", get(views::greet_world))
|
||||||
|
.route("/hello-world-text", get(views::greet_world_text));
|
||||||
|
|
||||||
|
let assets_dir = ServeDir::new("./assets");
|
||||||
|
let state = Arc::new(State::new().await?);
|
||||||
|
|
||||||
|
let live_reload_layer = LiveReloadLayer::new();
|
||||||
|
let reloader = live_reload_layer.reloader();
|
||||||
|
|
||||||
|
let mut watcher = notify::recommended_watcher(move |_| reloader.reload())?;
|
||||||
|
watcher.watch(Path::new("assets"), notify::RecursiveMode::Recursive)?;
|
||||||
|
|
||||||
|
let router = Router::new()
|
||||||
|
.fallback(|| async { (StatusCode::NOT_FOUND, "404 page not found") })
|
||||||
|
.nest("/app", app_router)
|
||||||
|
.nest_service("/assets", assets_dir)
|
||||||
|
.route("/", get(views::index))
|
||||||
|
.route("/register", get(views::register))
|
||||||
|
.with_state(state)
|
||||||
|
.layer(live_reload_layer);
|
||||||
|
|
||||||
|
Ok(router)
|
||||||
|
}
|
|
@ -4,6 +4,6 @@ diesel::table! {
|
||||||
users (id) {
|
users (id) {
|
||||||
id -> Nullable<Text>,
|
id -> Nullable<Text>,
|
||||||
name -> Nullable<Text>,
|
name -> Nullable<Text>,
|
||||||
hashed_password -> Nullable<Text>,
|
hashed_password -> Nullable<Binary>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
13
src/server.rs
Normal file
13
src/server.rs
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
use std::net::SocketAddr;
|
||||||
|
|
||||||
|
use axum::Router;
|
||||||
|
use tracing::info;
|
||||||
|
|
||||||
|
pub async fn listen(r: Router) {
|
||||||
|
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
|
||||||
|
info!("Listening on '{}'", addr);
|
||||||
|
axum::Server::bind(&addr)
|
||||||
|
.serve(r.into_make_service())
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
}
|
15
src/state.rs
Normal file
15
src/state.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
use crate::database;
|
||||||
|
|
||||||
|
pub struct State {
|
||||||
|
pub database: database::Database,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl State {
|
||||||
|
pub async fn new() -> Result<Self, anyhow::Error> {
|
||||||
|
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||||
|
let database = database::Database::new(database_url).await?;
|
||||||
|
Ok(State { database })
|
||||||
|
}
|
||||||
|
}
|
70
src/views.rs
Normal file
70
src/views.rs
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
use axum::response::Html;
|
||||||
|
use maud::html;
|
||||||
|
use tracing::instrument;
|
||||||
|
|
||||||
|
use crate::partials::{footer, header};
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub async fn index() -> Html<String> {
|
||||||
|
Html(
|
||||||
|
html! {
|
||||||
|
(header())
|
||||||
|
main class="prose" {
|
||||||
|
h1 { "Manage live lyrics and music displays" }
|
||||||
|
p { "Stop struggling to share the same messy set of PowerPoint files or Google Presentations. Make editing and controlling your live lyrics and music displays easy and simple." }
|
||||||
|
ul {
|
||||||
|
li { "Live collaboration with your team" }
|
||||||
|
li { "Fully compatible with any device" }
|
||||||
|
li { "Simple workflow" }
|
||||||
|
li { "Dark theme and light theme" }
|
||||||
|
li { "Generous free plan" }
|
||||||
|
li { "Lightweight and fast" }
|
||||||
|
}
|
||||||
|
section class="flex gap" {
|
||||||
|
button hx-get="/register" hx-target="body>main" hx-push-url="true" class="button bg-primary" { "Try now" }
|
||||||
|
a class="button" href="/login" { "Login" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(footer())
|
||||||
|
}
|
||||||
|
.into_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub async fn register() -> Html<String> {
|
||||||
|
Html(
|
||||||
|
html! {
|
||||||
|
h1 { "Register an account" }
|
||||||
|
p { "Stop struggling to share the same messy set of PowerPoint files or Google Presentations. Make editing and controlling your live lyrics and music displays easy and simple." }
|
||||||
|
ul {
|
||||||
|
li { "Live collaboration with your team" }
|
||||||
|
li { "Fully compatible with any device" }
|
||||||
|
li { "Simple workflow" }
|
||||||
|
li { "Dark theme and light theme" }
|
||||||
|
li { "Generous free plan" }
|
||||||
|
li { "Lightweight and fast" }
|
||||||
|
}
|
||||||
|
section class="flex gap" {
|
||||||
|
a class="button bg-primary" href="/register/anonymous" { "Try now" }
|
||||||
|
a class="button" href="/login" { "Login" }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.into_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub async fn greet_world() -> Html<String> {
|
||||||
|
Html(
|
||||||
|
html! {
|
||||||
|
h1 { (greet_world_text().await) }
|
||||||
|
}
|
||||||
|
.into_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub async fn greet_world_text() -> &'static str {
|
||||||
|
"Hello, World!"
|
||||||
|
}
|
Loading…
Reference in a new issue