diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 90deb1aa2..607147a0b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # Contributing to Loco -Thank you for taking the time to read this. +Thank you for taking the time to read this. The first way to show support is to star our repos :). @@ -21,7 +21,7 @@ Feature requests from anyone is definitely welcomed! You can open an [issue](htt ## I want to support -Awesome! The best way to support us is to recommend it to your classmates/colleagues/friends, write blog posts and tutorials on our projects and help out other users in the community. +Awesome! The best way to support us is to recommend it to your classmates/colleagues/friends, write blog posts and tutorials on our projects and help out other users in the community. ## I want to join @@ -56,7 +56,7 @@ You can see how we test in [.github/workflows](.github/workflows/) #### Snapshots To update/create a snapshots we are using [insta](https://github.com/mitsuhiko/insta). all you need to do is install insta and run the following command: ``` -cargo install test --review +cargo insta test --review ``` In case of cli changes we snapshot the binary commands. in case of changes run the following command yo update the CLI snapshot @@ -73,7 +73,7 @@ then cd to `docs-site` and run `zola serve` The most recommended and straightforward method to contribute changes to the project involves forking it on GitHub and subsequently initiating a pull request to propose the integration of your modifications into our repository. -Changes a starters project are not recommended. read more [here](./starters/README.md) +Changes a starters project are not recommended. read more [here](./starters/README.md) ### In Your Pull Request Description, Include: - References to any bugs fixed by the change @@ -84,6 +84,3 @@ Changes a starters project are not recommended. read more [here](./starters/READ - be based on the master branch - adhere to the code [style](#code-style) - Successfully passes the [test suite](#testing) - - - diff --git a/examples/demo/Cargo.lock b/examples/demo/Cargo.lock index fce7cded5..053332ec0 100644 --- a/examples/demo/Cargo.lock +++ b/examples/demo/Cargo.lock @@ -458,6 +458,34 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core 0.3.4", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http 0.2.11", + "http-body 0.4.6", + "hyper 0.14.28", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "axum" version = "0.7.4" @@ -465,7 +493,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1236b4b292f6c4d6dc34604bb5120d85c3fe1d1aa596bd5cc52ca054d13e7b9e" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.4.3", "axum-macros", "bytes", "futures-util", @@ -494,6 +522,23 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 0.2.11", + "http-body 0.4.6", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-core" version = "0.4.3" @@ -521,8 +566,8 @@ version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "895ff42f72016617773af68fb90da2a9677d89c62338ec09162d4909d86fdd8f" dependencies = [ - "axum", - "axum-core", + "axum 0.7.4", + "axum-core 0.4.3", "bytes", "cookie", "futures-util", @@ -555,7 +600,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b683cbc43010e9a3d72c2f31ca464155ff4f95819e88a32924b0f47a43898978" dependencies = [ - "axum", + "axum 0.7.4", "bytes", "futures", "futures-core", @@ -580,7 +625,7 @@ dependencies = [ "anyhow", "async-trait", "auto-future", - "axum", + "axum 0.7.4", "bytes", "cookie", "http 1.0.0", @@ -600,6 +645,24 @@ dependencies = [ "url", ] +[[package]] +name = "axum-tracing-opentelemetry" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26965dca35be1ca4a128177b9302c4c04f0661443621171adb09d002dcdf1d5" +dependencies = [ + "axum 0.7.4", + "futures-core", + "futures-util", + "http 1.0.0", + "opentelemetry", + "pin-project-lite", + "tower", + "tracing", + "tracing-opentelemetry", + "tracing-opentelemetry-instrumentation-sdk", +] + [[package]] name = "axum_session" version = "0.10.1" @@ -608,8 +671,8 @@ checksum = "d98669d6e652c4688e12f5d9f9a6a0077f5be101a1bfaa169062d3df70ad4e38" dependencies = [ "aes-gcm", "async-trait", - "axum-core", - "base64", + "axum-core 0.4.3", + "base64 0.21.7", "bytes", "chrono", "cookie", @@ -655,6 +718,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + [[package]] name = "base64" version = "0.21.7" @@ -732,13 +801,14 @@ name = "blo" version = "0.1.0" dependencies = [ "async-trait", - "axum", + "axum 0.7.4", "axum-extra", "axum-test", "axum_session", "chrono", "eyre", "fluent-templates", + "futures-util", "include_dir", "insta", "loco-extras", @@ -752,6 +822,7 @@ dependencies = [ "serial_test", "tera", "tokio", + "tower", "tracing", "tracing-subscriber", "trycmd", @@ -830,6 +901,27 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bson" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d43b38e074cc0de2957f10947e376a1d88b9c4dbab340b590800cc1b2e066b2" +dependencies = [ + "ahash 0.8.7", + "base64 0.13.1", + "bitvec", + "hex", + "indexmap 2.2.2", + "js-sys", + "once_cell", + "rand", + "serde", + "serde_bytes", + "serde_json", + "time", + "uuid", +] + [[package]] name = "bstr" version = "1.9.0" @@ -922,7 +1014,7 @@ checksum = "2d886547e41f740c616ae73108f6eb70afe6d940c7bc697cb30f13daec073037" dependencies = [ "camino", "cargo-platform", - "semver", + "semver 1.0.21", "serde", "serde_json", "thiserror", @@ -1026,7 +1118,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.0", ] [[package]] @@ -1113,6 +1205,12 @@ dependencies = [ "memchr", ] +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.18.0" @@ -1120,7 +1218,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cd91cf61412820176e137621345ee43b3f4423e589e7ae4e50d601d93e35ef8" dependencies = [ "aes-gcm", - "base64", + "base64 0.21.7", "percent-encoding", "rand", "subtle", @@ -1178,6 +1276,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.5" @@ -1267,6 +1374,41 @@ dependencies = [ "cipher", ] +[[package]] +name = "darling" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01d95850c592940db9b8194bc39f4bc0e89dee5c4265e4b1807c34a9aba453c" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "859d65a907b6852c9361e3185c862aae7fafd2887876799fa55f5f99dc40d610" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim 0.10.0", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.13.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c972679f83bdf9c42bd905396b6c3588a843a17f0f16dfcfa3e2c5d57441835" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + [[package]] name = "dashmap" version = "5.5.3" @@ -1280,6 +1422,12 @@ dependencies = [ "parking_lot_core", ] +[[package]] +name = "data-encoding" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" + [[package]] name = "der" version = "0.7.8" @@ -1312,6 +1460,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "derive_more" +version = "0.99.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version 0.4.0", + "syn 1.0.109", +] + [[package]] name = "deunicode" version = "1.4.2" @@ -1413,7 +1574,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75" dependencies = [ - "base64", + "base64 0.21.7", "memchr", ] @@ -1438,6 +1599,18 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "enum-as-inner" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21cdad81446a7f7dc43f6a77409efeb9733d2fa65553efef6018ef257c959b73" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "equivalent" version = "1.0.1" @@ -1925,6 +2098,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "h2" +version = "0.3.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http 0.2.11", + "indexmap 2.2.2", + "slab", + "tokio", + "tokio-util", + "tracing", +] + [[package]] name = "h2" version = "0.4.2" @@ -2158,6 +2350,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2 0.3.26", "http 0.2.11", "http-body 0.4.6", "httparse", @@ -2180,7 +2373,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2", + "h2 0.4.2", "http 1.0.0", "http-body 1.0.0", "httparse", @@ -2191,6 +2384,18 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper 0.14.28", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "hyper-util" version = "0.1.3" @@ -2234,6 +2439,23 @@ dependencies = [ "cc", ] +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +dependencies = [ + "matches", + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "idna" version = "0.4.0" @@ -2332,6 +2554,22 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "init-tracing-opentelemetry" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "754367a7e7f9314afe3ee9780ba8b8ea2cab487cdc8017c9794793051242f878" +dependencies = [ + "opentelemetry", + "opentelemetry-otlp", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "thiserror", + "tracing", + "tracing-opentelemetry", + "tracing-subscriber", +] + [[package]] name = "inout" version = "0.1.3" @@ -2397,6 +2635,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2 0.5.5", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + [[package]] name = "ipnet" version = "2.9.0" @@ -2442,7 +2692,7 @@ version = "9.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c7ea04a7c5c055c175f189b6dc6ba036fd62306b58c66c9f6389036c503a3f4" dependencies = [ - "base64", + "base64 0.21.7", "js-sys", "pem", "ring", @@ -2476,7 +2726,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357ff5edb6d8326473a64c82cf41ddf78ab116f89668c50c4fac1b321e5e80f4" dependencies = [ "async-trait", - "base64", + "base64 0.21.7", "chumsky", "email-encoding", "email_address", @@ -2494,7 +2744,7 @@ dependencies = [ "rustls-pemfile 2.0.0", "socket2 0.5.5", "tokio", - "tokio-rustls", + "tokio-rustls 0.25.0", "url", "webpki-roots 0.26.1", ] @@ -2566,12 +2816,21 @@ name = "loco-extras" version = "0.4.0" dependencies = [ "async-trait", - "axum", + "axum 0.7.4", "axum-prometheus", + "axum-tracing-opentelemetry", + "init-tracing-opentelemetry", "loco-rs", + "mongodb", + "opentelemetry", + "opentelemetry-otlp", + "serde", "serde_json", "tower", "tower-http", + "tracing", + "tracing-opentelemetry-instrumentation-sdk", + "tracing-subscriber", ] [[package]] @@ -2588,7 +2847,7 @@ version = "0.4.0" dependencies = [ "argon2", "async-trait", - "axum", + "axum 0.7.4", "axum-extra", "axum-test", "backtrace_printer", @@ -2642,6 +2901,15 @@ dependencies = [ "value-bag", ] +[[package]] +name = "lru-cache" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c" +dependencies = [ + "linked-hash-map", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -2657,6 +2925,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + [[package]] name = "matchit" version = "0.7.3" @@ -2695,7 +2969,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83a4c4718a371ddfb7806378f23617876eea8b82e5ff1324516bcd283249d9ea" dependencies = [ - "base64", + "base64 0.21.7", "hyper 0.14.28", "indexmap 1.9.3", "ipnet", @@ -2773,6 +3047,53 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mongodb" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef206acb1b72389b49bc9985efe7eb1f8a9bb18e5680d262fac26c07f44025f1" +dependencies = [ + "async-trait", + "base64 0.13.1", + "bitflags 1.3.2", + "bson", + "chrono", + "derivative", + "derive_more", + "futures-core", + "futures-executor", + "futures-io", + "futures-util", + "hex", + "hmac", + "lazy_static", + "md-5", + "pbkdf2", + "percent-encoding", + "rand", + "rustc_version_runtime", + "rustls 0.21.10", + "rustls-pemfile 1.0.4", + "serde", + "serde_bytes", + "serde_with", + "sha-1", + "sha2", + "socket2 0.4.10", + "stringprep", + "strsim 0.10.0", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "trust-dns-proto", + "trust-dns-resolver", + "typed-builder", + "uuid", + "webpki-roots 0.25.4", +] + [[package]] name = "multer" version = "3.0.0" @@ -2953,6 +3274,93 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +[[package]] +name = "opentelemetry" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900d57987be3f2aeb70d385fff9b27fb74c5723cc9a52d904d4f9c807a0667bf" +dependencies = [ + "futures-core", + "futures-sink", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + +[[package]] +name = "opentelemetry-http" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7690dc77bf776713848c4faa6501157469017eaf332baccd4eb1cea928743d94" +dependencies = [ + "async-trait", + "bytes", + "http 0.2.11", + "opentelemetry", +] + +[[package]] +name = "opentelemetry-otlp" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a016b8d9495c639af2145ac22387dcb88e44118e45320d9238fbf4e7889abcb" +dependencies = [ + "async-trait", + "futures-core", + "http 0.2.11", + "opentelemetry", + "opentelemetry-http", + "opentelemetry-proto", + "opentelemetry-semantic-conventions", + "opentelemetry_sdk", + "prost", + "thiserror", + "tokio", + "tonic", +] + +[[package]] +name = "opentelemetry-proto" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a8fddc9b68f5b80dae9d6f510b88e02396f006ad48cac349411fbecc80caae4" +dependencies = [ + "opentelemetry", + "opentelemetry_sdk", + "prost", + "tonic", +] + +[[package]] +name = "opentelemetry-semantic-conventions" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9ab5bd6c42fb9349dcf28af2ba9a0667f697f9bdcca045d39f2cec5543e2910" + +[[package]] +name = "opentelemetry_sdk" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e90c7113be649e31e9a0f8b5ee24ed7a16923b322c3c5ab6367469c049d6b7e" +dependencies = [ + "async-trait", + "crossbeam-channel", + "futures-channel", + "futures-executor", + "futures-util", + "glob", + "once_cell", + "opentelemetry", + "ordered-float 4.2.0", + "percent-encoding", + "rand", + "thiserror", + "tokio", + "tokio-stream", +] + [[package]] name = "ordered-float" version = "3.9.2" @@ -2962,6 +3370,15 @@ dependencies = [ "num-traits", ] +[[package]] +name = "ordered-float" +version = "4.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +dependencies = [ + "num-traits", +] + [[package]] name = "os_pipe" version = "1.1.5" @@ -3057,13 +3474,22 @@ version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", +] + [[package]] name = "pem" version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64", + "base64 0.21.7", "serde", ] @@ -3353,6 +3779,29 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "prost" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f5d036824e4761737860779c906171497f6d55681139d8312388f8fe398922" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9554e3ab233f0a932403704f1a1d08c30d5ccd931adfdfa1e8b5a19b52c1d55a" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 2.0.48", +] + [[package]] name = "psm" version = "0.1.21" @@ -3397,6 +3846,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + [[package]] name = "quote" version = "1.0.35" @@ -3612,6 +4067,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "resolv-conf" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52e44394d2086d010551b14b53b1f24e31647570cd1deb0379e2c21b329aba00" +dependencies = [ + "hostname", + "quick-error", +] + [[package]] name = "ring" version = "0.17.7" @@ -3703,7 +4168,7 @@ dependencies = [ "futures", "futures-timer", "rstest_macros", - "rustc_version", + "rustc_version 0.4.0", ] [[package]] @@ -3718,7 +4183,7 @@ dependencies = [ "quote", "regex", "relative-path", - "rustc_version", + "rustc_version 0.4.0", "syn 2.0.48", "unicode-ident", ] @@ -3767,13 +4232,32 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +[[package]] +name = "rustc_version" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +dependencies = [ + "semver 0.9.0", +] + [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver", + "semver 1.0.21", +] + +[[package]] +name = "rustc_version_runtime" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d31b7153270ebf48bf91c65ae5b0c00e749c4cfad505f66530ac74950249582f" +dependencies = [ + "rustc_version 0.2.3", + "semver 0.9.0", ] [[package]] @@ -3809,6 +4293,7 @@ version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ + "log", "ring", "rustls-webpki 0.101.7", "sct", @@ -3834,7 +4319,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] @@ -3843,7 +4328,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35e4980fa29e4c4b212ffb3db068a564cbf560e51d3944b7c88bd8bf5bec64f4" dependencies = [ - "base64", + "base64 0.21.7", "rustls-pki-types", ] @@ -4036,7 +4521,7 @@ dependencies = [ "chrono", "derivative", "inherent", - "ordered-float", + "ordered-float 3.9.2", "rust_decimal", "sea-query-derive", "serde_json", @@ -4117,6 +4602,15 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +dependencies = [ + "semver-parser", +] + [[package]] name = "semver" version = "1.0.21" @@ -4126,6 +4620,12 @@ dependencies = [ "serde", ] +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" + [[package]] name = "serde" version = "1.0.196" @@ -4135,6 +4635,15 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_bytes" +version = "0.11.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" +dependencies = [ + "serde", +] + [[package]] name = "serde_derive" version = "1.0.196" @@ -4152,6 +4661,7 @@ version = "1.0.113" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79" dependencies = [ + "indexmap 2.2.2", "itoa", "ryu", "serde", @@ -4207,6 +4717,28 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678b5a069e50bf00ecd22d0cd8ddf7c236f68581b03db652061ed5eb13a312ff" +dependencies = [ + "serde", + "serde_with_macros", +] + +[[package]] +name = "serde_with_macros" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e182d6ec6f05393cc0e5ed1bf81ad6db3a8feedf8ee515ecdd369809bcce8082" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "serde_yaml" version = "0.9.31" @@ -4245,6 +4777,17 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "sha-1" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5058ada175748e33390e40e872bd0fe59a19f265d0158daa551c5a88a76009c" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha1" version = "0.10.6" @@ -4647,7 +5190,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e37195395df71fd068f6e2082247891bc11e3289624bbc776a0cdfa1ca7f1ea4" dependencies = [ "atoi", - "base64", + "base64 0.21.7", "bigdecimal", "bitflags 2.4.2", "byteorder", @@ -4694,7 +5237,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6ac0ac3b7ccd10cc96c7ab29791a7dd236bd94021f31eec7ba3d46a74aa1c24" dependencies = [ "atoi", - "base64", + "base64 0.21.7", "bigdecimal", "bitflags 2.4.2", "byteorder", @@ -4788,6 +5331,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + [[package]] name = "strsim" version = "0.11.0" @@ -4846,6 +5395,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "take_mut" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f764005d11ee5f36500a149ace24e00e3da98b0158b3e2d53a7495660d3f4d60" + [[package]] name = "tap" version = "1.0.1" @@ -5014,6 +5569,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.2.0" @@ -5025,6 +5590,16 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.10", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.25.0" @@ -5055,6 +5630,7 @@ checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", "pin-project-lite", "tokio", @@ -5094,6 +5670,33 @@ dependencies = [ "winnow", ] +[[package]] +name = "tonic" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.6.20", + "base64 0.21.7", + "bytes", + "h2 0.3.26", + "http 0.2.11", + "http-body 0.4.6", + "hyper 0.14.28", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" @@ -5102,9 +5705,13 @@ checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" dependencies = [ "futures-core", "futures-util", + "indexmap 1.9.3", "pin-project", "pin-project-lite", + "rand", + "slab", "tokio", + "tokio-util", "tower-layer", "tower-service", "tracing", @@ -5193,6 +5800,36 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tracing-opentelemetry" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9be14ba1bbe4ab79e9229f7f89fab8d120b865859f10527f31c033e599d2284" +dependencies = [ + "js-sys", + "once_cell", + "opentelemetry", + "opentelemetry_sdk", + "smallvec", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", + "web-time", +] + +[[package]] +name = "tracing-opentelemetry-instrumentation-sdk" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a276058193f1b03d8279356215ec4c8c1bb21e40e5554bb239aa94fb2d8e189" +dependencies = [ + "http 1.0.0", + "opentelemetry", + "tracing", + "tracing-opentelemetry", +] + [[package]] name = "tracing-serde" version = "0.1.3" @@ -5224,6 +5861,51 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "trust-dns-proto" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c31f240f59877c3d4bb3b3ea0ec5a6a0cff07323580ff8c7a605cd7d08b255d" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.2.3", + "ipnet", + "lazy_static", + "log", + "rand", + "smallvec", + "thiserror", + "tinyvec", + "tokio", + "url", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ba72c2ea84515690c9fcef4c6c660bb9df3036ed1051686de84605b74fd558" +dependencies = [ + "cfg-if", + "futures-util", + "ipconfig", + "lazy_static", + "log", + "lru-cache", + "parking_lot", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "trust-dns-proto", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -5255,6 +5937,17 @@ dependencies = [ "rustc-hash", ] +[[package]] +name = "typed-builder" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89851716b67b937e393b3daa8423e67ddfc4bbbf1654bcf05488e95e0828db0c" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "typenum" version = "1.17.0" @@ -5657,6 +6350,16 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + [[package]] name = "webpki-roots" version = "0.25.4" @@ -5678,6 +6381,12 @@ version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22fc3756b8a9133049b26c7f61ab35416c130e8c09b660f5b3958b446f52cc50" +[[package]] +name = "widestring" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7219d36b6eac893fa81e84ebe06485e7dcbb616177469b142df14f1f4deb1311" + [[package]] name = "winapi" version = "0.3.9" @@ -5859,6 +6568,16 @@ dependencies = [ "memchr", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] + [[package]] name = "winsplit" version = "0.1.0" diff --git a/examples/demo/tests/models/snapshots/can_validate_model@users.snap b/examples/demo/tests/models/snapshots/can_validate_model@users.snap index 4d457a703..708479af8 100644 --- a/examples/demo/tests/models/snapshots/can_validate_model@users.snap +++ b/examples/demo/tests/models/snapshots/can_validate_model@users.snap @@ -1,5 +1,5 @@ --- -source: tests/models/main.rs +source: tests/models/users.rs expression: res --- Err( diff --git a/loco-extras/Cargo.toml b/loco-extras/Cargo.toml index 4eaaaec8f..31172c44c 100644 --- a/loco-extras/Cargo.toml +++ b/loco-extras/Cargo.toml @@ -27,6 +27,7 @@ init-tracing-opentelemetry = { version = "0.18", optional = true , features = [" tracing-opentelemetry-instrumentation-sdk = { version = "0.18", optional = true } tracing-subscriber = { version = "0.3.18", optional = true , features = ["env-filter", "json"] } tracing = { version = "0.1.40", optional = true } +mongodb = { version = "2.8.0", optional = true } [dependencies.loco-rs] path = "../" @@ -42,6 +43,7 @@ full = [ "initializer-multi-db", "initializer-normalize-path", "initializer-opentelemetry", + "initializer-mongodb", ] initializer-prometheus = ["dep:axum-prometheus"] @@ -49,4 +51,5 @@ initializer-extra-db = [] initializer-multi-db = ["dep:serde_json"] initializer-normalize-path = ["dep:tower", "dep:tower-http"] initializer-opentelemetry = ["dep:opentelemetry","dep:opentelemetry-otlp","dep:axum-tracing-opentelemetry", - "dep:init-tracing-opentelemetry", "dep:tracing-opentelemetry-instrumentation-sdk","dep:tracing-subscriber","dep:tracing"] \ No newline at end of file + "dep:init-tracing-opentelemetry", "dep:tracing-opentelemetry-instrumentation-sdk","dep:tracing-subscriber","dep:tracing"] +initializer-mongodb = ["dep:mongodb", "dep:serde", "dep:serde_json"] diff --git a/loco-extras/src/initializers/mod.rs b/loco-extras/src/initializers/mod.rs index 9a634f6fe..91d28a4ac 100644 --- a/loco-extras/src/initializers/mod.rs +++ b/loco-extras/src/initializers/mod.rs @@ -61,6 +61,8 @@ //!```` #[cfg(feature = "initializer-extra-db")] pub mod extra_db; +#[cfg(feature = "initializer-mongodb")] +pub mod mongodb; #[cfg(feature = "initializer-multi-db")] pub mod multi_db; #[cfg(feature = "initializer-normalize-path")] diff --git a/loco-extras/src/initializers/mongodb/README.md b/loco-extras/src/initializers/mongodb/README.md new file mode 100644 index 000000000..f5eaa7add --- /dev/null +++ b/loco-extras/src/initializers/mongodb/README.md @@ -0,0 +1,106 @@ +# This Initializer adds support for connection to a MongoDB database + +There is extra functionality that loco supports through the `loco_extras` crate. Each extra can be pulled in optionally and is intgerated into your loco app by adding them as intializers. + +This initializer adds support for using a MongoDB database. Choosing to use Mongo would mean sacrificing a lot of the features that loco provides out of the box, such as user authentication, but it can still be used quite effectively as loco will help with a lot of the boilerplate code. + +This initializer is recommended to be used with the base starter that does not come with a database connection (as those all use SQL), but it can be used with any other starter as well. + +## Steps + +To add this initializer to your project, follow these steps: + +### Add Dependencies + +Add the `mongodb` crate and mongodb initializer to your loco project. + +```toml +# Cargo.toml +[dependencies] +loco-extras = { version = "*", features = ["mongodb"] } +mongodb = { version = "2.8.0"} +``` + +### Add to the Config + +Add a mongodb connection section to you config.yaml file. + +```yaml +# config/[development/test/production...].yaml +initializers: + mongodb: + uri: {{ get_env(name="MONGODB_URI", default="mongodb://localhost:27017/") }} + db_name: "db_name" + client_options: + connectTimeout: + secs: 2 + nanos: 0 + serverSelectionTimeout: + secs: 2 + nanos: 0 +``` + +Although untested, the `client_options` should be able to take any options that the mongodb driver supports. The options are passed as a `serde_json::Value`, so however that type is serialized/deserialized should work here. Example above shows how `Duration` is serialized. + + +### Add the Initializer + +Add the initializer to your `src/app.rs` file. + +```rust +// src/app.rs +pub struct App; +#[async_trait] +impl Hooks for App { + // Other code... + async fn initializers(ctx: &AppContext) -> Result>> { + let mut initializers: Vec> = vec![ + Box::new(loco_extras::initializers::mongodb::MongoDbInitializer), + ]; + + Ok(initializers) + } + // Other code... +} +``` + +### Using the Connection + +Now you can use the connection in your handler code. + +```rust +// src/controllers/mongo.rs +use axum::Extension; +use loco_rs::prelude::*; +use serde_json::Value; +use mongodb::{bson::doc, Database}; + +pub async fn fetch(Extension(mongodb): Extension) -> Result { + let user: Option = mongodb.collection("users").find_one(doc!{}, None).await.map_err(|_| Error::NotFound)?; + format::json(user.ok_or_else(|| Error::NotFound)?) +} + +pub fn routes() -> Routes { + Routes::new() + .prefix("mongo") + .add("/", get(fetch)) +} +``` + +If you are adding a new file, don't forget to add it to the `src/controllers/mod.rs` file. + +### Adding to the Router + +If you created a new controller, you need to register the routes in your `src/app.rs` file. + +```rust +// src/app.rs + +fn routes(ctx: &AppContext) -> AppRoutes { + AppRoutes::with_default_routes() + // Other routes... + .add_route(controllers::mongodb::routes()) +} +``` + +Now you can run the server with the config information set OR set the `MONGODB_URI` environment variable. diff --git a/loco-extras/src/initializers/mongodb/mod.rs b/loco-extras/src/initializers/mongodb/mod.rs new file mode 100644 index 000000000..a7e013c67 --- /dev/null +++ b/loco-extras/src/initializers/mongodb/mod.rs @@ -0,0 +1,116 @@ +use async_trait::async_trait; +use axum::{Extension, Router as AxumRouter}; +use loco_rs::prelude::*; + +use mongodb::{bson::doc, options::ClientOptions, Client, Database}; + +#[allow(clippy::module_name_repetitions)] +pub struct MongoDbInitializer; + +#[async_trait] +impl Initializer for MongoDbInitializer { + fn name(&self) -> String { + "mongodb".to_string() + } + + async fn after_routes(&self, router: AxumRouter, ctx: &AppContext) -> Result { + let mongo_db_config = ctx + .config + .initializers + .clone() + .ok_or_else(|| Error::Message("initializers config not configured".to_string()))?; + + let mongo_db_value = mongo_db_config + .get("mongodb") + .ok_or_else(|| Error::Message("mongo not configured as initializer".to_string()))?; + + let mongo_db: MongoDbConfig = serde_json::from_value(mongo_db_value.clone()) + .map_err(|e| Error::Message(e.to_string()))?; + + let db = connect_to_db(mongo_db).await?; + + Ok(router.layer(Extension(db))) + } +} + +#[derive(Debug, Clone, serde::Deserialize)] +struct MongoDbConfig { + uri: String, + db_name: String, + client_options: Option, +} + +async fn connect_to_db(config: MongoDbConfig) -> Result { + let mut client_options = ClientOptions::parse_async(&config.uri) + .await + .map_err(|e| Error::Message(e.to_string()))?; + + let client_options = merge_config_with_client(&mut client_options, config.clone()); + + let client = Client::with_options(client_options).map_err(|e| Error::Message(e.to_string()))?; + + let db = client.database(config.db_name.as_ref()); + + // Ping the Database to make sure a connection has been made + db.run_command(doc! { "ping": 1 }, None) + .await + .map_err(|e| Error::Message(e.to_string()))?; + + Ok(db) +} + +fn merge_config_with_client(co: &mut ClientOptions, config: MongoDbConfig) -> ClientOptions { + match config.client_options { + None => co.clone(), + Some(client_options) => { + co.app_name = client_options.app_name.or(co.app_name.clone()); + co.compressors = client_options.compressors.or(co.compressors.clone()); + co.cmap_event_handler = client_options + .cmap_event_handler + .or(co.cmap_event_handler.clone()); + co.command_event_handler = client_options + .command_event_handler + .or(co.command_event_handler.clone()); + co.connect_timeout = client_options + .connect_timeout + .or(co.connect_timeout.clone()); + co.credential = client_options.credential.or(co.credential.clone()); + co.direct_connection = client_options + .direct_connection + .or(co.direct_connection.clone()); + co.driver_info = client_options.driver_info.or(co.driver_info.clone()); + co.heartbeat_freq = client_options.heartbeat_freq.or(co.heartbeat_freq.clone()); + co.load_balanced = client_options.load_balanced.or(co.load_balanced.clone()); + co.local_threshold = client_options + .local_threshold + .or(co.local_threshold.clone()); + co.max_idle_time = client_options.max_idle_time.or(co.max_idle_time.clone()); + co.max_pool_size = client_options.max_pool_size.or(co.max_pool_size.clone()); + co.min_pool_size = client_options.min_pool_size.or(co.min_pool_size.clone()); + co.max_connecting = client_options.max_connecting.or(co.max_connecting.clone()); + co.read_concern = client_options.read_concern.or(co.read_concern.clone()); + co.repl_set_name = client_options.repl_set_name.or(co.repl_set_name.clone()); + co.retry_reads = client_options.retry_reads.or(co.retry_reads.clone()); + co.retry_writes = client_options.retry_writes.or(co.retry_writes.clone()); + co.sdam_event_handler = client_options + .sdam_event_handler + .or(co.sdam_event_handler.clone()); + co.selection_criteria = client_options + .selection_criteria + .or(co.selection_criteria.clone()); + co.server_api = client_options.server_api.or(co.server_api.clone()); + co.server_selection_timeout = client_options + .server_selection_timeout + .or(co.server_selection_timeout.clone()); + co.default_database = client_options + .default_database + .or(co.default_database.clone()); + co.tls = client_options.tls.or(co.tls.clone()); + // co.tracing_max_document_length_bytes = client_options.tracing_max_document_length_bytes; + co.write_concern = client_options.write_concern.or(co.write_concern.clone()); + co.srv_max_hosts = client_options.srv_max_hosts.or(co.srv_max_hosts.clone()); + + co.clone() + } + } +}