From 7bcdc1113a5805cab68930ed13d1bd802f333f4e Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Wed, 4 Dec 2024 12:54:13 +0200 Subject: [PATCH 01/11] impl: #1000 - doctor check loco version (#1048) * impl: #1000 --- Cargo.toml | 1 + examples/demo/Cargo.lock | 555 ++++++++++++++++++++++++++++- examples/demo/tests/cmd/cli.trycmd | 2 +- src/doctor.rs | 81 ++++- src/errors.rs | 6 + 5 files changed, 636 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 7b7fe14be..5c1fc6e2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,6 +53,7 @@ backtrace_printer = { version = "1.3.0" } # cli clap = { version = "4.4.7", features = ["derive"], optional = true } colored = "2" +reqwest = { version = "0.12.7", features = ["json"] } sea-orm = { version = "1.1.0", features = [ diff --git a/examples/demo/Cargo.lock b/examples/demo/Cargo.lock index 990878120..1c18600ef 100644 --- a/examples/demo/Cargo.lock +++ b/examples/demo/Cargo.lock @@ -70,6 +70,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", + "getrandom", "once_cell", "version_check", "zerocopy", @@ -1016,6 +1017,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -1141,6 +1152,29 @@ dependencies = [ "typenum", ] +[[package]] +name = "cssparser" +version = "0.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c66d1cd8ed61bf80b38432613a7a2f09401ab8d0501110655f8b341484a3e3" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf", + "smallvec", +] + +[[package]] +name = "cssparser-macros" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" +dependencies = [ + "quote", + "syn 2.0.87", +] + [[package]] name = "ctr" version = "0.9.2" @@ -1252,6 +1286,17 @@ dependencies = [ "serde", ] +[[package]] +name = "derive_more" +version = "0.99.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "deunicode" version = "1.6.0" @@ -1333,6 +1378,21 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + [[package]] name = "duct" version = "0.13.7" @@ -1360,6 +1420,12 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +[[package]] +name = "ego-tree" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c6ba7d4eec39eaa9ab24d44a0e73a7949a1095a8b3f3abb11eddf27dbb56a53" + [[package]] name = "either" version = "1.13.0" @@ -1602,6 +1668,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1626,6 +1707,16 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + [[package]] name = "futures" version = "0.3.31" @@ -1745,6 +1836,15 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -1765,6 +1865,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "getopts" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14dbbfd5c71d70241ecf9e6f13737f7b5ce823821063188d7e46c41d371eebd5" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -1836,6 +1945,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "h2" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http 1.1.0", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "hashbrown" version = "0.12.3" @@ -1938,6 +2066,20 @@ dependencies = [ "windows", ] +[[package]] +name = "html5ever" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e15626aaf9c351bc696217cbe29cb9b5e86c43f8a46b5e2f5c6c5cf7cb904ce" +dependencies = [ + "log", + "mac", + "markup5ever", + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "http" version = "0.2.12" @@ -2035,6 +2177,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", + "h2", "http 1.1.0", "http-body", "httparse", @@ -2046,6 +2189,39 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08afdbb5c31130e3034af566421053ab03787c640246a446327f550d11bcb333" +dependencies = [ + "futures-util", + "http 1.1.0", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.10" @@ -2334,6 +2510,12 @@ dependencies = [ "unic-langid", ] +[[package]] +name = "ipnet" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" + [[package]] name = "ipnetwork" version = "0.20.0" @@ -2530,7 +2712,7 @@ dependencies = [ [[package]] name = "loco-gen" -version = "0.13.0" +version = "0.13.2" dependencies = [ "chrono", "clap", @@ -2546,7 +2728,7 @@ dependencies = [ [[package]] name = "loco-rs" -version = "0.13.1" +version = "0.13.2" dependencies = [ "argon2", "async-trait", @@ -2578,7 +2760,9 @@ dependencies = [ "object_store", "rand", "regex", + "reqwest", "rusty-sidekiq", + "scraper", "sea-orm", "sea-orm-migration", "semver", @@ -2589,6 +2773,7 @@ dependencies = [ "sqlx", "tera", "thiserror", + "thousands", "tokio", "tokio-cron-scheduler", "tokio-util", @@ -2612,6 +2797,26 @@ dependencies = [ "value-bag", ] +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "markup5ever" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82c88c6129bd24319e62a0359cb6b958fa7e8be6e19bb1663bc396b90883aca5" +dependencies = [ + "log", + "phf", + "phf_codegen", + "string_cache", + "string_cache_codegen", + "tendril", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2732,6 +2937,29 @@ dependencies = [ "version_check", ] +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nom" version = "7.1.3" @@ -2884,6 +3112,50 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" +dependencies = [ + "bitflags", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "ordered-float" version = "3.9.2" @@ -3065,7 +3337,8 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" dependencies = [ - "phf_shared", + "phf_macros", + "phf_shared 0.11.2", ] [[package]] @@ -3074,8 +3347,18 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.2", + "phf_shared 0.11.2", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand", ] [[package]] @@ -3084,10 +3367,32 @@ version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" dependencies = [ - "phf_shared", + "phf_shared 0.11.2", "rand", ] +[[package]] +name = "phf_macros" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +dependencies = [ + "phf_generator 0.11.2", + "phf_shared 0.11.2", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher", +] + [[package]] name = "phf_shared" version = "0.11.2" @@ -3189,6 +3494,12 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "pretty_assertions" version = "1.4.1" @@ -3505,6 +3816,49 @@ dependencies = [ "bytecheck", ] +[[package]] +name = "reqwest" +version = "0.12.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a77c62af46e79de0a562e1a9849205ffcb7fc1238876e9bd743357570e04046f" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http 1.1.0", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "system-configuration", + "tokio", + "tokio-native-tls", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows-registry", +] + [[package]] name = "reserve-port" version = "2.0.1" @@ -3793,12 +4147,37 @@ dependencies = [ "sdd", ] +[[package]] +name = "schannel" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scraper" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0e749d29b2064585327af5038a5a8eb73aeebad4a3472e83531a436563f7208" +dependencies = [ + "ahash 0.8.11", + "cssparser", + "ego-tree", + "getopts", + "html5ever", + "precomputed-hash", + "selectors", + "tendril", +] + [[package]] name = "sdd" version = "3.0.4" @@ -3970,6 +4349,48 @@ version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa39c7303dc58b5543c94d22c1766b0d31f2ee58306363ea622b10bbc075eaa2" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "selectors" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd568a4c9bb598e291a08244a5c1f5a8a6650bee243b5b0f8dbb3d9cc1d87fe8" +dependencies = [ + "bitflags", + "cssparser", + "derive_more", + "fxhash", + "log", + "new_debug_unreachable", + "phf", + "phf_codegen", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "self_cell" version = "0.10.3" @@ -4111,6 +4532,15 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "servo_arc" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae65c4249478a2647db249fb43e23cec56a2c8974a427e7bd8cb5a1d0964921a" +dependencies = [ + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4620,6 +5050,32 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +[[package]] +name = "string_cache" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" +dependencies = [ + "new_debug_unreachable", + "once_cell", + "parking_lot", + "phf_shared 0.10.0", + "precomputed-hash", + "serde", +] + +[[package]] +name = "string_cache_codegen" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro2", + "quote", +] + [[package]] name = "stringprep" version = "0.1.5" @@ -4682,6 +5138,9 @@ name = "sync_wrapper" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +dependencies = [ + "futures-core", +] [[package]] name = "synstructure" @@ -4694,6 +5153,27 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e1d1b10ced5ca923a1fcb8d03e96b8d3268065d724548c0211415ff6ac6bac4" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -4719,6 +5199,17 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "tera" version = "1.20.0" @@ -4772,6 +5263,12 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "thousands" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bf63baf9f5039dadc247375c29eb13706706cfde997d0330d05aa63a77d8820" + [[package]] name = "thread_local" version = "1.1.8" @@ -4882,6 +5379,16 @@ dependencies = [ "syn 2.0.87", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.26.0" @@ -5341,6 +5848,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf16_iter" version = "1.0.5" @@ -5650,6 +6163,36 @@ dependencies = [ "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]] name = "windows-sys" version = "0.48.0" diff --git a/examples/demo/tests/cmd/cli.trycmd b/examples/demo/tests/cmd/cli.trycmd index 9320015b1..cd5df6fd2 100644 --- a/examples/demo/tests/cmd/cli.trycmd +++ b/examples/demo/tests/cmd/cli.trycmd @@ -133,7 +133,7 @@ $ demo_app-cli doctor ✅ DB connection: success ✅ redis queue: queue connection: success ✅ Dependencies - +✅ Loco version: latest ``` diff --git a/src/doctor.rs b/src/doctor.rs index e90ee5773..1b12cb2cf 100644 --- a/src/doctor.rs +++ b/src/doctor.rs @@ -7,6 +7,7 @@ use std::{ use colored::Colorize; use regex::Regex; use semver::Version; +use serde::Deserialize; use crate::{ bgworker, @@ -39,6 +40,51 @@ fn get_min_dep_versions() -> &'static HashMap<&'static str, &'static str> { }) } +#[derive(Deserialize)] +struct CrateResponse { + #[serde(rename = "crate")] + krate: CrateInfo, +} + +#[derive(Deserialize)] +struct CrateInfo { + max_version: String, +} + +/// .Check latest crate version in crates.io +/// +/// # Errors +/// +/// This function will return an error if it fails +pub async fn check_cratesio_version( + crate_name: &str, + current_version: &str, +) -> Result> { + // Construct the URL for the crates.io API + let url = format!("https://crates.io/api/v1/crates/{crate_name}"); + + let client = reqwest::Client::new(); + // Fetch crate information + let response = client + .get(&url) + .header("User-Agent", "Loco-Version-Check/1.0") + .send() + .await? + .json::() + .await?; + + // Parse versions + let current = Version::parse(current_version)?; + let latest = Version::parse(&response.krate.max_version)?; + + // Compare versions + if latest > current { + Ok(Some(response.krate.max_version)) + } else { + Ok(None) + } +} + /// Represents different resources that can be checked. #[derive(PartialOrd, PartialEq, Eq, Ord, Debug)] pub enum Resource { @@ -46,6 +92,7 @@ pub enum Resource { Database, Queue, Deps, + PublishedLocoVersion, } /// Represents the status of a resource check. @@ -129,6 +176,10 @@ pub async fn run_all(config: &Config, production: bool) -> Result Result { let crate_statuses = depcheck::check_crate_versions(&cargolock, get_min_dep_versions().clone())?; let mut report = String::new(); - report.push_str("Dependencies\n"); + report.push_str("Dependencies"); let mut all_ok = true; for status in &crate_statuses { @@ -155,7 +206,7 @@ pub fn check_deps() -> Result { } = &status.status { report.push_str(&format!( - " {}: version {} does not meet minimum version {}\n", + "\n {}: version {} does not meet minimum version {}", status.crate_name.yellow(), version.red(), min_version.green() @@ -281,3 +332,29 @@ pub fn check_seaorm_cli() -> Result { }), } } + +/// Check for the latest Loco version +/// +/// # Errors +/// +/// This function will return an error if it fails +pub async fn check_published_loco_version() -> Result { + let compiled_version = env!("CARGO_PKG_VERSION"); + match check_cratesio_version("loco-rs", compiled_version).await { + Ok(Some(v)) => Ok(Check { + status: CheckStatus::NotOk, + message: format!("Loco version: `{compiled_version}`, latest version: `{v}`"), + description: Some("It is recommended to upgrade your main Loco version.".to_string()), + }), + Ok(None) => Ok(Check { + status: CheckStatus::Ok, + message: "Loco version: latest".to_string(), + description: None, + }), + Err(e) => Ok(Check { + status: CheckStatus::NotOk, + message: format!("Checking Loco version failed: {e}"), + description: None, + }), + } +} diff --git a/src/errors.rs b/src/errors.rs index a70aa02c2..d26a101f0 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -148,6 +148,12 @@ pub enum Error { #[error(transparent)] VersionCheck(#[from] depcheck::VersionCheckError), + #[error(transparent)] + RequestError(#[from] reqwest::Error), + + #[error(transparent)] + SemVer(#[from] semver::Error), + #[error(transparent)] Any(#[from] Box), } From e50eecf6548cc589095d967d37c3225fd6cad6cc Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Wed, 4 Dec 2024 11:58:15 +0200 Subject: [PATCH 02/11] fix: make model types public --- src/db.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/db.rs b/src/db.rs index 88945f9f7..1494d89d7 100644 --- a/src/db.rs +++ b/src/db.rs @@ -400,7 +400,7 @@ fn fix_entities() -> AppResult<()> { &new_file, format!( r"use sea_orm::entity::prelude::*; -use super::_entities::{module}::{{ActiveModel, Entity}}; +pub use super::_entities::{module}::{{ActiveModel, Entity}}; pub type {module_pascal} = Entity; #[async_trait::async_trait] From 41270e98db97ab5acb06e1dcdeda36072c9b63e7 Mon Sep 17 00:00:00 2001 From: Serhii Potapov Date: Thu, 5 Dec 2024 12:35:35 +0100 Subject: [PATCH 03/11] Tiny doc improvement: prefer let mut item: ActiveModel = Default::default(); (#1042) * Prefer let mut item: ActiveModel = Default::default(); --- .../content/docs/getting-started/guide.md | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/docs-site/content/docs/getting-started/guide.md b/docs-site/content/docs/getting-started/guide.md index 4f2f11465..da7dc4443 100644 --- a/docs-site/content/docs/getting-started/guide.md +++ b/docs-site/content/docs/getting-started/guide.md @@ -550,9 +550,7 @@ pub async fn list(State(ctx): State) -> Result { } pub async fn add(State(ctx): State, Json(params): Json) -> Result { - let mut item = ActiveModel { - ..Default::default() - }; + let mut item: ActiveModel = Default::default(); params.update(&mut item); let item = item.insert(&ctx.db).await?; format::json(item) @@ -586,7 +584,7 @@ pub fn routes() -> Routes { .add("/", post(add)) .add("/:id", get(get_one)) .add("/:id", delete(remove)) - .add("/:id", post(update)) + .add("/:id", patch(update)) } ``` @@ -678,7 +676,7 @@ pub fn routes() -> Routes { // .add("/", get(list)) // .add("/:id", get(get_one)) // .add("/:id", delete(remove)) - // .add("/:id", post(update)) + // .add("/:id", patch(update)) } ``` @@ -855,9 +853,7 @@ Go back to `src/controllers/comments.rs` and take a look at the `add` function: ```rust pub async fn add(State(ctx): State, Json(params): Json) -> Result { - let mut item = ActiveModel { - ..Default::default() - }; + let mut item: ActiveModel = Default::default(); params.update(&mut item); let item = item.insert(&ctx.db).await?; format::json(item) @@ -872,16 +868,14 @@ async fn add( State(ctx): State, Json(params): Json, ) -> Result { - // we only want to make sure it exists - let _current_user = crate::models::users::Model::find_by_pid(&ctx.db, &auth.claims.pid).await?; - - // next, update - // homework/bonus: make a comment _actually_ belong to user (user_id) - let mut item = ActiveModel { - ..Default::default() - }; - params.update(&mut item); - let item = item.insert(&ctx.db).await?; - format::json(item) + // we only want to make sure it exists + let _current_user = crate::models::users::Model::find_by_pid(&ctx.db, &auth.claims.pid).await?; + + // next, update + // homework/bonus: make a comment _actually_ belong to user (user_id) + let mut item: ActiveModel = Default::default(); + params.update(&mut item); + let item = item.insert(&ctx.db).await?; + format::json(item) } ``` From 40fca68e54741dc9f10b8cfd4a0a92faf1e1b7d9 Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Fri, 6 Dec 2024 09:59:25 +0200 Subject: [PATCH 04/11] restructure templates --- loco-gen/src/lib.rs | 33 +++++++--------- loco-gen/src/model.rs | 4 +- loco-gen/src/templates/controller.t | 35 ----------------- .../docker/docker.t} | 0 .../docker/ignore.t} | 0 .../nginx/nginx.t} | 0 .../shuttle/config.t} | 0 .../shuttle/shuttle.t} | 0 .../{mailer_html.t => mailer/html.t} | 0 loco-gen/src/templates/{ => mailer}/mailer.t | 0 .../{mailer_sub.t => mailer/subject.t} | 0 .../{mailer_text.t => mailer/text.t} | 0 .../src/templates/{ => migration}/migration.t | 0 loco-gen/src/templates/{ => model}/model.t | 0 .../templates/{model_test.t => model/test.t} | 0 loco-gen/src/templates/request_test.t | 39 ------------------- .../src/templates/{ => scheduler}/scheduler.t | 0 loco-gen/src/templates/{ => task}/task.t | 0 .../templates/{task_test.t => task/test.t} | 0 .../{worker_test.t => worker/test.t} | 0 loco-gen/src/templates/{ => worker}/worker.t | 0 21 files changed, 17 insertions(+), 94 deletions(-) delete mode 100644 loco-gen/src/templates/controller.t rename loco-gen/src/templates/{deployment_docker.t => deployment/docker/docker.t} (100%) rename loco-gen/src/templates/{deployment_docker_ignore.t => deployment/docker/ignore.t} (100%) rename loco-gen/src/templates/{deployment_nginx.t => deployment/nginx/nginx.t} (100%) rename loco-gen/src/templates/{deployment_shuttle_config.t => deployment/shuttle/config.t} (100%) rename loco-gen/src/templates/{deployment_shuttle.t => deployment/shuttle/shuttle.t} (100%) rename loco-gen/src/templates/{mailer_html.t => mailer/html.t} (100%) rename loco-gen/src/templates/{ => mailer}/mailer.t (100%) rename loco-gen/src/templates/{mailer_sub.t => mailer/subject.t} (100%) rename loco-gen/src/templates/{mailer_text.t => mailer/text.t} (100%) rename loco-gen/src/templates/{ => migration}/migration.t (100%) rename loco-gen/src/templates/{ => model}/model.t (100%) rename loco-gen/src/templates/{model_test.t => model/test.t} (100%) delete mode 100644 loco-gen/src/templates/request_test.t rename loco-gen/src/templates/{ => scheduler}/scheduler.t (100%) rename loco-gen/src/templates/{ => task}/task.t (100%) rename loco-gen/src/templates/{task_test.t => task/test.t} (100%) rename loco-gen/src/templates/{worker_test.t => worker/test.t} (100%) rename loco-gen/src/templates/{ => worker}/worker.t (100%) diff --git a/loco-gen/src/lib.rs b/loco-gen/src/lib.rs index 2f5f11daa..90ed56a93 100644 --- a/loco-gen/src/lib.rs +++ b/loco-gen/src/lib.rs @@ -15,30 +15,27 @@ mod scaffold; mod testutil; use std::{str::FromStr, sync::OnceLock}; -const CONTROLLER_T: &str = include_str!("templates/controller.t"); -const CONTROLLER_TEST_T: &str = include_str!("templates/request_test.t"); +const MAILER_T: &str = include_str!("templates/mailer/mailer.t"); +const MAILER_SUB_T: &str = include_str!("templates/mailer/subject.t"); +const MAILER_TEXT_T: &str = include_str!("templates/mailer/text.t"); +const MAILER_HTML_T: &str = include_str!("templates/mailer/html.t"); -const MAILER_T: &str = include_str!("templates/mailer.t"); -const MAILER_SUB_T: &str = include_str!("templates/mailer_sub.t"); -const MAILER_TEXT_T: &str = include_str!("templates/mailer_text.t"); -const MAILER_HTML_T: &str = include_str!("templates/mailer_html.t"); +const MIGRATION_T: &str = include_str!("templates/migration/migration.t"); -const MIGRATION_T: &str = include_str!("templates/migration.t"); +const TASK_T: &str = include_str!("templates/task/task.t"); +const TASK_TEST_T: &str = include_str!("templates/task/test.t"); -const TASK_T: &str = include_str!("templates/task.t"); -const TASK_TEST_T: &str = include_str!("templates/task_test.t"); +const SCHEDULER_T: &str = include_str!("templates/scheduler/scheduler.t"); -const SCHEDULER_T: &str = include_str!("templates/scheduler.t"); - -const WORKER_T: &str = include_str!("templates/worker.t"); -const WORKER_TEST_T: &str = include_str!("templates/worker_test.t"); +const WORKER_T: &str = include_str!("templates/worker/worker.t"); +const WORKER_TEST_T: &str = include_str!("templates/worker/test.t"); // Deployment templates -const DEPLOYMENT_DOCKER_T: &str = include_str!("templates/deployment_docker.t"); -const DEPLOYMENT_DOCKER_IGNORE_T: &str = include_str!("templates/deployment_docker_ignore.t"); -const DEPLOYMENT_SHUTTLE_T: &str = include_str!("templates/deployment_shuttle.t"); -const DEPLOYMENT_SHUTTLE_CONFIG_T: &str = include_str!("templates/deployment_shuttle_config.t"); -const DEPLOYMENT_NGINX_T: &str = include_str!("templates/deployment_nginx.t"); +const DEPLOYMENT_DOCKER_T: &str = include_str!("templates/deployment/docker/docker.t"); +const DEPLOYMENT_DOCKER_IGNORE_T: &str = include_str!("templates/deployment/docker/ignore.t"); +const DEPLOYMENT_SHUTTLE_T: &str = include_str!("templates/deployment/shuttle/shuttle.t"); +const DEPLOYMENT_SHUTTLE_CONFIG_T: &str = include_str!("templates/deployment/shuttle/config.t"); +const DEPLOYMENT_NGINX_T: &str = include_str!("templates/deployment/nginx/nginx.t"); const DEPLOYMENT_SHUTTLE_RUNTIME_VERSION: &str = "0.46.0"; diff --git a/loco-gen/src/model.rs b/loco-gen/src/model.rs index 0e1a74041..928f280be 100644 --- a/loco-gen/src/model.rs +++ b/loco-gen/src/model.rs @@ -8,8 +8,8 @@ use serde_json::json; use super::{Error, Result}; use crate::get_mappings; -const MODEL_T: &str = include_str!("templates/model.t"); -const MODEL_TEST_T: &str = include_str!("templates/model_test.t"); +const MODEL_T: &str = include_str!("templates/model/model.t"); +const MODEL_TEST_T: &str = include_str!("templates/model/test.t"); use super::{collect_messages, AppInfo}; diff --git a/loco-gen/src/templates/controller.t b/loco-gen/src/templates/controller.t deleted file mode 100644 index c1b4c202d..000000000 --- a/loco-gen/src/templates/controller.t +++ /dev/null @@ -1,35 +0,0 @@ -{% set file_name = name | snake_case -%} -{% set module_name = file_name | pascal_case -%} -to: src/controllers/{{ file_name }}.rs -skip_exists: true -message: "Controller `{{module_name}}` was added successfully." -injections: -- into: src/controllers/mod.rs - append: true - content: "pub mod {{ file_name }};" -- into: src/app.rs - after: "AppRoutes::" - content: " .add_route(controllers::{{ file_name }}::routes())" ---- -#![allow(clippy::unused_async)] -use loco_rs::prelude::*; -use axum::debug_handler; - - -#[debug_handler] -pub async fn echo(req_body: String) -> String { - req_body -} - -#[debug_handler] -pub async fn hello(State(_ctx): State) -> Result { - // do something with context (database, etc) - format::text("hello") -} - -pub fn routes() -> Routes { - Routes::new() - .prefix("{{ name | snake_case }}") - .add("/", get(hello)) - .add("/echo", post(echo)) -} diff --git a/loco-gen/src/templates/deployment_docker.t b/loco-gen/src/templates/deployment/docker/docker.t similarity index 100% rename from loco-gen/src/templates/deployment_docker.t rename to loco-gen/src/templates/deployment/docker/docker.t diff --git a/loco-gen/src/templates/deployment_docker_ignore.t b/loco-gen/src/templates/deployment/docker/ignore.t similarity index 100% rename from loco-gen/src/templates/deployment_docker_ignore.t rename to loco-gen/src/templates/deployment/docker/ignore.t diff --git a/loco-gen/src/templates/deployment_nginx.t b/loco-gen/src/templates/deployment/nginx/nginx.t similarity index 100% rename from loco-gen/src/templates/deployment_nginx.t rename to loco-gen/src/templates/deployment/nginx/nginx.t diff --git a/loco-gen/src/templates/deployment_shuttle_config.t b/loco-gen/src/templates/deployment/shuttle/config.t similarity index 100% rename from loco-gen/src/templates/deployment_shuttle_config.t rename to loco-gen/src/templates/deployment/shuttle/config.t diff --git a/loco-gen/src/templates/deployment_shuttle.t b/loco-gen/src/templates/deployment/shuttle/shuttle.t similarity index 100% rename from loco-gen/src/templates/deployment_shuttle.t rename to loco-gen/src/templates/deployment/shuttle/shuttle.t diff --git a/loco-gen/src/templates/mailer_html.t b/loco-gen/src/templates/mailer/html.t similarity index 100% rename from loco-gen/src/templates/mailer_html.t rename to loco-gen/src/templates/mailer/html.t diff --git a/loco-gen/src/templates/mailer.t b/loco-gen/src/templates/mailer/mailer.t similarity index 100% rename from loco-gen/src/templates/mailer.t rename to loco-gen/src/templates/mailer/mailer.t diff --git a/loco-gen/src/templates/mailer_sub.t b/loco-gen/src/templates/mailer/subject.t similarity index 100% rename from loco-gen/src/templates/mailer_sub.t rename to loco-gen/src/templates/mailer/subject.t diff --git a/loco-gen/src/templates/mailer_text.t b/loco-gen/src/templates/mailer/text.t similarity index 100% rename from loco-gen/src/templates/mailer_text.t rename to loco-gen/src/templates/mailer/text.t diff --git a/loco-gen/src/templates/migration.t b/loco-gen/src/templates/migration/migration.t similarity index 100% rename from loco-gen/src/templates/migration.t rename to loco-gen/src/templates/migration/migration.t diff --git a/loco-gen/src/templates/model.t b/loco-gen/src/templates/model/model.t similarity index 100% rename from loco-gen/src/templates/model.t rename to loco-gen/src/templates/model/model.t diff --git a/loco-gen/src/templates/model_test.t b/loco-gen/src/templates/model/test.t similarity index 100% rename from loco-gen/src/templates/model_test.t rename to loco-gen/src/templates/model/test.t diff --git a/loco-gen/src/templates/request_test.t b/loco-gen/src/templates/request_test.t deleted file mode 100644 index 08d02f0a1..000000000 --- a/loco-gen/src/templates/request_test.t +++ /dev/null @@ -1,39 +0,0 @@ -{% set file_name = name | snake_case -%} -{% set module_name = file_name | pascal_case -%} -to: tests/requests/{{ file_name }}.rs -skip_exists: true -message: "Tests for controller `{{module_name}}` was added successfully. Run `cargo test`." -injections: -- into: tests/requests/mod.rs - append: true - content: "pub mod {{ file_name }};" ---- -use {{pkg_name}}::app::App; -use loco_rs::testing::prelude::*; -use serial_test::serial; - -#[tokio::test] -#[serial] -async fn can_get_echo() { - request::(|request, _ctx| async move { - let payload = serde_json::json!({ - "foo": "bar", - }); - - let res = request.post("/{{ name | snake_case }}/echo").json(&payload).await; - assert_eq!(res.status_code(), 200); - assert_eq!(res.text(), serde_json::to_string(&payload).unwrap()); - }) - .await; -} - -#[tokio::test] -#[serial] -async fn can_request_root() { - request::(|request, _ctx| async move { - let res = request.get("/{{ name | snake_case }}").await; - assert_eq!(res.status_code(), 200); - assert_eq!(res.text(), "hello"); - }) - .await; -} diff --git a/loco-gen/src/templates/scheduler.t b/loco-gen/src/templates/scheduler/scheduler.t similarity index 100% rename from loco-gen/src/templates/scheduler.t rename to loco-gen/src/templates/scheduler/scheduler.t diff --git a/loco-gen/src/templates/task.t b/loco-gen/src/templates/task/task.t similarity index 100% rename from loco-gen/src/templates/task.t rename to loco-gen/src/templates/task/task.t diff --git a/loco-gen/src/templates/task_test.t b/loco-gen/src/templates/task/test.t similarity index 100% rename from loco-gen/src/templates/task_test.t rename to loco-gen/src/templates/task/test.t diff --git a/loco-gen/src/templates/worker_test.t b/loco-gen/src/templates/worker/test.t similarity index 100% rename from loco-gen/src/templates/worker_test.t rename to loco-gen/src/templates/worker/test.t diff --git a/loco-gen/src/templates/worker.t b/loco-gen/src/templates/worker/worker.t similarity index 100% rename from loco-gen/src/templates/worker.t rename to loco-gen/src/templates/worker/worker.t From 4f1cad51fb72c05a2f33308886e9baf8085a22cf Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Fri, 6 Dec 2024 10:30:24 +0200 Subject: [PATCH 05/11] docs: seo + broken links --- docs-site/config.toml | 2 +- .../casts/003-scaffolding-crud-with-html.md | 2 +- docs-site/content/casts/005-testing-tasks.md | 8 ++-- docs-site/content/casts/006-mailers.md | 2 +- docs-site/content/docs/the-app/controller.md | 2 +- docs-site/templates/base.html | 37 +++++++++++++++++++ 6 files changed, 45 insertions(+), 8 deletions(-) diff --git a/docs-site/config.toml b/docs-site/config.toml index 3133b8eeb..20a1448cf 100644 --- a/docs-site/config.toml +++ b/docs-site/config.toml @@ -1,6 +1,6 @@ # The URL the site will be built for base_url = "https://loco.rs" -title = "Loco" +title = "Loco.rs - Productivity-first Rust Fullstack Web Framework" description = "Loco is a productivity-first web and service framework in Rust" diff --git a/docs-site/content/casts/003-scaffolding-crud-with-html.md b/docs-site/content/casts/003-scaffolding-crud-with-html.md index cdee166f7..d9f7395b4 100644 --- a/docs-site/content/casts/003-scaffolding-crud-with-html.md +++ b/docs-site/content/casts/003-scaffolding-crud-with-html.md @@ -17,6 +17,6 @@ id = "EircfwF8c0E" Reference material for this episode: -* Loco.rs docs: [routes in controllers](https://loco.rs/docs/getting-started/scaffold/) +* Loco.rs docs: [routes in controllers](https://loco.rs/docs/the-app/controller/#routes-in-controllers) * The [SaaS starter](https://loco.rs/docs/starters/saas/) * The [REST API starter](https://loco.rs/docs/starters/rest-api/) diff --git a/docs-site/content/casts/005-testing-tasks.md b/docs-site/content/casts/005-testing-tasks.md index 6ae56741e..19c339879 100644 --- a/docs-site/content/casts/005-testing-tasks.md +++ b/docs-site/content/casts/005-testing-tasks.md @@ -17,7 +17,7 @@ id = "485JlLA-T6U" Reference material for this episode: -* Loco.rs docs: [routes in controllers](https://loco.rs/docs/the-app/task/) -* The [SaaS starter](https://loco.rs/docs/starters/saas/) -* The [REST API starter](https://loco.rs/docs/starters/rest-api/) -* The [Lightweight starter](https://loco.rs/docs/starters/service/) +* Loco.rs docs: [routes in controllers](https://loco.rs/docs/processing/task/) +* The [SaaS starter](https://loco.rs/docs/getting-started/starters/#saas-starter) +* The [REST API starter](https://loco.rs/docs/getting-started/starters/#rest-api-starter) +* The [Lightweight starter](https://loco.rs/docs/getting-started/starters/#lightweight-service-starter) diff --git a/docs-site/content/casts/006-mailers.md b/docs-site/content/casts/006-mailers.md index 9ee3a8431..3d9501ee7 100644 --- a/docs-site/content/casts/006-mailers.md +++ b/docs-site/content/casts/006-mailers.md @@ -16,4 +16,4 @@ id = "ieGeihxLGC8" Reference material for this episode: -* Loco.rs docs: [Mailers](https://loco.rs/docs/the-app/mailers/) +* Loco.rs docs: [Mailers](https://loco.rs/docs/processing/mailers/) diff --git a/docs-site/content/docs/the-app/controller.md b/docs-site/content/docs/the-app/controller.md index 09dd7ef06..c4f4b6233 100644 --- a/docs-site/content/docs/the-app/controller.md +++ b/docs-site/content/docs/the-app/controller.md @@ -722,7 +722,7 @@ middlewares: `Loco` also allow us to apply [layers](https://docs.rs/tower/latest/tower/trait.Layer.html) to specific handlers or routes. -For more information on handler and route based middleware, refer to the [middleware](/docs/the-app/middlewares) +For more information on handler and route based middleware, refer to the [middleware](/docs/the-app/controller/#middleware) documentation. diff --git a/docs-site/templates/base.html b/docs-site/templates/base.html index 82da86e0d..02c2a934a 100644 --- a/docs-site/templates/base.html +++ b/docs-site/templates/base.html @@ -12,6 +12,43 @@ + {# Site title #} + {% set current_path = current_path | default(value="/") %} + {% if current_path == "/" %} + + {{ config.title | default(value="Home") }} + + + {% else %} + + {% if page.title %} {{ page.title ~ " - Loco.rs" }} + {% elif section.title %} {{ section.title ~ " - Loco.rs" }} + {% elif config.title %} {{ config.title }} + {% else %} Post ~ " - Loco.rs" {% endif %} + + + {% if not page_has_og_title %} + + {% endif %} + {% endif %} + + {% if not page_has_og_description %} + {% if page.description %} + + {% elif config.description %} + + {% endif %} + {% endif %} + + {% if not page_has_description %} + {% if page.description %} + + {% elif config.description %} + + {% endif %} + {% endif %} + + From f23462314c5b64bf4e3f6f9b151d095a47053892 Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Fri, 6 Dec 2024 10:43:55 +0200 Subject: [PATCH 06/11] docs: more seo --- docs-site/config.toml | 2 +- docs-site/templates/base.html | 45 +++++++++++++++++++++++++---------- 2 files changed, 33 insertions(+), 14 deletions(-) diff --git a/docs-site/config.toml b/docs-site/config.toml index 20a1448cf..de12a6648 100644 --- a/docs-site/config.toml +++ b/docs-site/config.toml @@ -1,7 +1,7 @@ # The URL the site will be built for base_url = "https://loco.rs" title = "Loco.rs - Productivity-first Rust Fullstack Web Framework" -description = "Loco is a productivity-first web and service framework in Rust" +description = "Loco.rs is like Ruby on Rails for Rust. Use it to quickly build and deploy Rust based apps from zero to production." # Whether to automatically compile all Sass files in the sass directory diff --git a/docs-site/templates/base.html b/docs-site/templates/base.html index 02c2a934a..0d7c06b05 100644 --- a/docs-site/templates/base.html +++ b/docs-site/templates/base.html @@ -12,14 +12,34 @@ - {# Site title #} - {% set current_path = current_path | default(value="/") %} - {% if current_path == "/" %} + {% if page.extra.meta %} + + {% for data in page.extra.meta %} + + {% endfor %} + {% endif %} + + {# Site title #} + {% set current_path = current_path | default(value="/") %} + {% if current_path == "/" %} {{ config.title | default(value="Home") }} - {% else %} + {% else %} {% if page.title %} {{ page.title ~ " - Loco.rs" }} {% elif section.title %} {{ section.title ~ " - Loco.rs" }} @@ -27,10 +47,13 @@ {% else %} Post ~ " - Loco.rs" {% endif %} - {% if not page_has_og_title %} - - {% endif %} - {% endif %} + {% if not page_has_og_title %} + + + + {% endif %} + {% endif %} + {% if not page_has_og_description %} {% if page.description %} @@ -53,14 +76,10 @@ - - - - + - From f7f82ccd90662cdd3b6c57d9faf476a5a20a9775 Mon Sep 17 00:00:00 2001 From: Tommy McCormick Date: Fri, 6 Dec 2024 15:24:53 -0500 Subject: [PATCH 07/11] chore(deps): use rustls with reqwest rather than openssl --- Cargo.toml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 5c1fc6e2b..0ee1de140 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,7 +53,13 @@ backtrace_printer = { version = "1.3.0" } # cli clap = { version = "4.4.7", features = ["derive"], optional = true } colored = "2" -reqwest = { version = "0.12.7", features = ["json"] } +reqwest = { version = "0.12.7", features = [ + "charset", + "http2", + "json", + "macos-system-configuration", + "rustls-tls", +], default-features = false } sea-orm = { version = "1.1.0", features = [ From 661aebe04ad82b7e6dbdf79bcfac00008e77e69e Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Sat, 7 Dec 2024 09:29:17 +0200 Subject: [PATCH 08/11] impl: more flexible config, take more values from ENV --- loco-new/base_template/config/development.yaml.t | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/loco-new/base_template/config/development.yaml.t b/loco-new/base_template/config/development.yaml.t index cd1bf250d..21168b4e8 100644 --- a/loco-new/base_template/config/development.yaml.t +++ b/loco-new/base_template/config/development.yaml.t @@ -7,7 +7,7 @@ logger: # Enable pretty backtrace (sets RUST_BACKTRACE=1) pretty_backtrace: true # Log level, options: trace, debug, info, warn or error. - level: debug + level: {{ get_env(name="LOG_LEVEL", default="debug") }} # Define the logging format. options: compact, pretty or json format: compact # By default the logger has filtering only logs that came from your code or logs that came from `loco` framework. to see all third party libraries @@ -17,7 +17,9 @@ logger: # Web server configuration server: # Port on which the server will listen. the server binding is 0.0.0.0:{PORT} - port: 5150 + port: {{ get_env(name="PORT", default="5150") }} + # Binding for the server (which interface to bind to) + binding: {{ get_env(name="BINDING", default="localhost") }} # The UI hostname or IP address that mailers will point to. host: http://localhost # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block @@ -99,7 +101,7 @@ database: # Database connection URI uri: {% raw %}{{{% endraw %} get_env(name="DATABASE_URL", default="{{settings.db.endpoint | replace(from='NAME', to=settings.package_name) | replace(from='ENV', to='development')}}") {% raw %}}}{% endraw %} # When enabled, the sql query will be logged. - enable_logging: false + enable_logging: {{ get_env(name="DB_LOGGING", default="false") }} # Set the timeout duration when acquiring a connection. connect_timeout: {% raw %}{{{% endraw %} get_env(name="DB_CONNECT_TIMEOUT", default="500") {% raw %}}}{% endraw %} # Set the idle duration before closing a connection. From 1737be8fc63dab8be9f7f9b54732442b59750a4d Mon Sep 17 00:00:00 2001 From: Tommy McCormick <16668493+mccormickt@users.noreply.github.com> Date: Sun, 8 Dec 2024 01:41:23 -0500 Subject: [PATCH 09/11] feat(mailer): expose hello_name for SMTP client config (#1057) * feat(mailer): expose hello_name for SMTP client config * chore: add commented out config for mailer hello name to template --- loco-new/base_template/config/development.yaml.t | 12 +++++++----- src/config.rs | 2 ++ src/mailer/email_sender.rs | 9 +++++++-- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/loco-new/base_template/config/development.yaml.t b/loco-new/base_template/config/development.yaml.t index cd1bf250d..259657ae2 100644 --- a/loco-new/base_template/config/development.yaml.t +++ b/loco-new/base_template/config/development.yaml.t @@ -22,8 +22,8 @@ server: host: http://localhost # Out of the box middleware configuration. to disable middleware you can changed the `enable` field to `false` of comment the middleware block middlewares: - {%- if settings.asset %} - {%- if settings.asset.kind == "server" %} + {%- if settings.asset %} + {%- if settings.asset.kind == "server" %} static: enable: true must_exist: true @@ -32,7 +32,7 @@ server: uri: "/static" path: "assets/static" fallback: "assets/static/404.html" - {%- elif settings.asset.kind == "client" %} + {%- elif settings.asset.kind == "client" %} static: enable: true must_exist: true @@ -42,9 +42,9 @@ server: path: "frontend/dist" fallback: "frontend/dist/index.html" {%- endif -%} - + {%- endif -%} - + {%- if settings.background%} # Worker Configuration @@ -83,6 +83,8 @@ mailer: # auth: # user: # password: + # Override the SMTP hello name (default is the machine's hostname) + # hello_name: {%- endif %} # Initializers Configuration diff --git a/src/config.rs b/src/config.rs index 31eeccb1a..340159230 100644 --- a/src/config.rs +++ b/src/config.rs @@ -500,6 +500,8 @@ pub struct SmtpMailer { pub secure: bool, /// Auth SMTP server pub auth: Option, + /// Optional EHLO client ID instead of hostname + pub hello_name: Option, } /// Authentication details for the mailer diff --git a/src/mailer/email_sender.rs b/src/mailer/email_sender.rs index e392365b5..3cb2b86ca 100644 --- a/src/mailer/email_sender.rs +++ b/src/mailer/email_sender.rs @@ -3,8 +3,9 @@ //! sending emails with options like sender, recipient, subject, and content. use lettre::{ - message::MultiPart, transport::smtp::authentication::Credentials, AsyncTransport, Message, - Tokio1Executor, Transport, + message::MultiPart, + transport::smtp::{authentication::Credentials, extension::ClientId}, + AsyncTransport, Message, Tokio1Executor, Transport, }; use tracing::error; @@ -60,6 +61,10 @@ impl EmailSender { .credentials(Credentials::new(auth.user.clone(), auth.password.clone())); } + if let Some(hello_name) = config.hello_name.as_ref() { + email_builder = email_builder.hello_name(ClientId::Domain(hello_name.clone())); + } + Ok(Self { transport: EmailTransport::Smtp(email_builder.build()), }) From 9130f18cbbd3203c8cccd2bf603573e298879347 Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Sat, 7 Dec 2024 09:34:07 +0200 Subject: [PATCH 10/11] impl: add convenience funcs to ModelError --- src/model/mod.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/model/mod.rs b/src/model/mod.rs index 749b9ea8c..d454e4848 100644 --- a/src/model/mod.rs +++ b/src/model/mod.rs @@ -35,11 +35,30 @@ pub enum ModelError { #[error(transparent)] Any(#[from] Box), + + #[error("{0}")] + Message(String), } #[allow(clippy::module_name_repetitions)] pub type ModelResult = std::result::Result; +impl ModelError { + #[must_use] + pub fn wrap(err: impl std::error::Error + Send + Sync + 'static) -> Self { + Self::Any(Box::new(err)) + } + + #[must_use] + pub fn to_msg(err: impl std::error::Error + Send + Sync + 'static) -> Self { + Self::Message(err.to_string()) + } + + #[must_use] + pub fn msg(s: &str) -> Self { + Self::Message(s.to_string()) + } +} #[async_trait] pub trait Authenticable: Clone { async fn find_by_api_key(db: &DatabaseConnection, api_key: &str) -> ModelResult; From b79b78830c81f8a466dc1ab3b8b1499cacfe5c07 Mon Sep 17 00:00:00 2001 From: "Dotan J. Nahum" Date: Sat, 7 Dec 2024 09:50:53 +0200 Subject: [PATCH 11/11] impl: better model starter --- src/db.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/db.rs b/src/db.rs index 1494d89d7..e233c846b 100644 --- a/src/db.rs +++ b/src/db.rs @@ -400,13 +400,11 @@ fn fix_entities() -> AppResult<()> { &new_file, format!( r"use sea_orm::entity::prelude::*; -pub use super::_entities::{module}::{{ActiveModel, Entity}}; +pub use super::_entities::{module}::{{ActiveModel, Model, Entity}}; pub type {module_pascal} = Entity; #[async_trait::async_trait] impl ActiveModelBehavior for ActiveModel {{ - // extend activemodel below (keep comment for generators) - async fn before_save(self, _db: &C, insert: bool) -> std::result::Result where C: ConnectionTrait, @@ -420,6 +418,15 @@ impl ActiveModelBehavior for ActiveModel {{ }} }} }} + +// implement your read-oriented logic here +impl Model {{}} + +// implement your write-oriented logic here +impl ActiveModel {{}} + +// implement your custom finders, selectors oriented logic here +impl Entity {{}} " ), )?;