From a58df1cb8ed983562fbb2a69bee2f0a8a6824b2e Mon Sep 17 00:00:00 2001 From: Gabriel Kaszewski Date: Sun, 20 Jul 2025 13:38:44 +0200 Subject: [PATCH] init --- .env.example | 2 + .gitignore | 2 + Cargo.lock | 3126 +++++++++++++++++++++ Cargo.toml | 22 + Dockerfile | 24 + compose.yml | 26 + frontend/.gitignore | 24 + frontend/README.md | 69 + frontend/bun.lockb | Bin 0 -> 99074 bytes frontend/eslint.config.js | 23 + frontend/index.html | 13 + frontend/package.json | 31 + frontend/public/favicon.ico | Bin 0 -> 15951 bytes frontend/public/morty.png | Bin 0 -> 22290 bytes frontend/src/App.tsx | 137 + frontend/src/api.ts | 14 + frontend/src/components/card.tsx | 62 + frontend/src/components/table-element.tsx | 10 + frontend/src/components/table.tsx | 11 + frontend/src/index.css | 42 + frontend/src/main.tsx | 10 + frontend/src/types.ts | 21 + frontend/src/utils.ts | 9 + frontend/src/vite-env.d.ts | 1 + frontend/tsconfig.app.json | 27 + frontend/tsconfig.json | 7 + frontend/tsconfig.node.json | 25 + frontend/vite.config.ts | 8 + src/bin/fetch_characters.rs | 127 + src/db.rs | 11 + src/lib.rs | 4 + src/main.rs | 59 + src/models/mod.rs | 27 + src/routes/mod.rs | 125 + src/utils.rs | 9 + 35 files changed, 4108 insertions(+) create mode 100644 .env.example create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 Dockerfile create mode 100644 compose.yml create mode 100644 frontend/.gitignore create mode 100644 frontend/README.md create mode 100755 frontend/bun.lockb create mode 100644 frontend/eslint.config.js create mode 100644 frontend/index.html create mode 100644 frontend/package.json create mode 100644 frontend/public/favicon.ico create mode 100644 frontend/public/morty.png create mode 100644 frontend/src/App.tsx create mode 100644 frontend/src/api.ts create mode 100644 frontend/src/components/card.tsx create mode 100644 frontend/src/components/table-element.tsx create mode 100644 frontend/src/components/table.tsx create mode 100644 frontend/src/index.css create mode 100644 frontend/src/main.tsx create mode 100644 frontend/src/types.ts create mode 100644 frontend/src/utils.ts create mode 100644 frontend/src/vite-env.d.ts create mode 100644 frontend/tsconfig.app.json create mode 100644 frontend/tsconfig.json create mode 100644 frontend/tsconfig.node.json create mode 100644 frontend/vite.config.ts create mode 100644 src/bin/fetch_characters.rs create mode 100644 src/db.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 src/models/mod.rs create mode 100644 src/routes/mod.rs create mode 100644 src/utils.rs diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..63e0c93 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +MONGODB_URI=mongodb://localhost:27017 +DB_NAME=rick_and_morty \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..0b745e2 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +.env \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..c657c26 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,3126 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "getrandom 0.3.3", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + +[[package]] +name = "anyhow" +version = "1.0.98" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" + +[[package]] +name = "async-trait" +version = "0.1.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e539d3fca749fcee5236ab05e93a52867dd549cc157c8cb7f99595f3cedffdb5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + +[[package]] +name = "autocfg" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" + +[[package]] +name = "axum" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "021e862c184ae977658b36c4500f7feac3221ca5da43e3f25bd04ab6c79a29b5" +dependencies = [ + "axum-core", + "axum-macros", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "backtrace" +version = "0.3.75" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets 0.52.6", +] + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" + +[[package]] +name = "bitvec" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" +dependencies = [ + "funty", + "radium", + "tap", + "wyz", +] + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bson" +version = "2.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969a9ba84b0ff843813e7249eed1678d9b6607ce5a3b8f0a47af3fcf7978e6e" +dependencies = [ + "ahash", + "base64 0.22.1", + "bitvec", + "getrandom 0.2.16", + "getrandom 0.3.3", + "hex", + "indexmap 2.10.0", + "js-sys", + "once_cell", + "rand 0.9.1", + "serde", + "serde_bytes", + "serde_json", + "time", + "uuid", +] + +[[package]] +name = "bumpalo" +version = "3.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" + +[[package]] +name = "bytes" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" + +[[package]] +name = "cc" +version = "1.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362" +dependencies = [ + "shlex", +] + +[[package]] +name = "cfg-if" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" + +[[package]] +name = "chrono" +version = "0.4.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-link", +] + +[[package]] +name = "const-random" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" +dependencies = [ + "const-random-macro", +] + +[[package]] +name = "const-random-macro" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" +dependencies = [ + "getrandom 0.2.16", + "once_cell", + "tiny-keccak", +] + +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "cpufeatures" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "darling" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.104", +] + +[[package]] +name = "darling_macro" +version = "0.20.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "data-encoding" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" + +[[package]] +name = "deranged" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e" +dependencies = [ + "powerfmt", + "serde", +] + +[[package]] +name = "derive-syn-parse" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d65d7ce8132b7c0e54497a4d9a55a1c2a0912a0d786cf894472ba818fba45762" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "derive-where" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "510c292c8cf384b1a340b816a9a6cf2599eb8f566a44949024af88418000c50b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "derive_more" +version = "0.99.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" +dependencies = [ + "convert_case", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.104", +] + +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", + "subtle", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + +[[package]] +name = "dyn-clone" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enum-as-inner" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +dependencies = [ + "libc", + "windows-sys 0.59.0", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fnv" +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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "funty" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-io", + "futures-macro", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasi 0.14.2+wasi-0.2.4", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "h2" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17da50a276f1e01e0ba6c029e47b7100754904ee8a278f886546e98575380785" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap 2.10.0", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "hashbrown" +version = "0.15.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hickory-proto" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna", + "ipnet", + "once_cell", + "rand 0.8.5", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand 0.8.5", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "http" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls 0.23.28", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.2", + "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.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" + +[[package]] +name = "icu_properties" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "potential_utf", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" + +[[package]] +name = "icu_provider" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +dependencies = [ + "displaydoc", + "icu_locale_core", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe4cd85333e22411419a0bcae1297d25e58c9443848b11dc6a86fefe8c78a661" +dependencies = [ + "equivalent", + "hashbrown 0.15.4", + "serde", +] + +[[package]] +name = "io-uring" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" +dependencies = [ + "bitflags 2.9.1", + "cfg-if", + "libc", +] + +[[package]] +name = "ipconfig" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f" +dependencies = [ + "socket2", + "widestring", + "windows-sys 0.48.0", + "winreg", +] + +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" + +[[package]] +name = "js-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.174" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" + +[[package]] +name = "linked-hash-map" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" + +[[package]] +name = "linux-raw-sys" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" + +[[package]] +name = "litemap" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" + +[[package]] +name = "lock_api" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" + +[[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 = "macro_magic" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc33f9f0351468d26fbc53d9ce00a096c8522ecb42f19b50f34f2c422f76d21d" +dependencies = [ + "macro_magic_core", + "macro_magic_macros", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "macro_magic_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1687dc887e42f352865a393acae7cf79d98fab6351cde1f58e9e057da89bf150" +dependencies = [ + "const-random", + "derive-syn-parse", + "macro_magic_core_macros", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "macro_magic_core_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b02abfe41815b5bd98dbd4260173db2c116dda171dc0fe7838cb206333b83308" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "macro_magic_macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ea28ee64b88876bf45277ed9a5817c1817df061a74f2b988971a12570e5869" +dependencies = [ + "macro_magic_core", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata 0.1.10", +] + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + +[[package]] +name = "memchr" +version = "2.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +dependencies = [ + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.59.0", +] + +[[package]] +name = "mongodb" +version = "3.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0f8c69f13acf07eae386a2974f48ffd9187ea2aba8defbea9aa34e7e272c5f3" +dependencies = [ + "async-trait", + "base64 0.13.1", + "bitflags 1.3.2", + "bson", + "chrono", + "derive-where", + "derive_more", + "futures-core", + "futures-executor", + "futures-io", + "futures-util", + "hex", + "hickory-proto", + "hickory-resolver", + "hmac", + "macro_magic", + "md-5", + "mongodb-internal-macros", + "once_cell", + "pbkdf2", + "percent-encoding", + "rand 0.8.5", + "rustc_version_runtime", + "rustls 0.21.12", + "rustls-pemfile", + "serde", + "serde_bytes", + "serde_with", + "sha1", + "sha2", + "socket2", + "stringprep", + "strsim", + "take_mut", + "thiserror", + "tokio", + "tokio-rustls 0.24.1", + "tokio-util", + "typed-builder", + "uuid", + "webpki-roots", +] + +[[package]] +name = "mongodb-internal-macros" +version = "3.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9202de265a3a8bbb43f9fe56db27c93137d4f9fb04c093f47e9c7de0c61ac7d" +dependencies = [ + "macro_magic", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "native-tls" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi", +] + +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "openssl" +version = "0.10.73" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +dependencies = [ + "bitflags 2.9.1", + "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.104", +] + +[[package]] +name = "openssl-probe" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" + +[[package]] +name = "openssl-sys" +version = "0.9.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "overload" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "parking_lot" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets 0.52.6", +] + +[[package]] +name = "pbkdf2" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917" +dependencies = [ + "digest", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pkg-config" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" + +[[package]] +name = "potential_utf" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585" +dependencies = [ + "zerovec", +] + +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + +[[package]] +name = "proc-macro2" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha 0.3.1", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" +dependencies = [ + "rand_chacha 0.9.0", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.4", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.3", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom 0.2.16", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.3", +] + +[[package]] +name = "redox_syscall" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "ref-cast" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" +dependencies = [ + "ref-cast-impl", +] + +[[package]] +name = "ref-cast-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "regex" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax 0.6.29", +] + +[[package]] +name = "regex-automata" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.8.5", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "reqwest" +version = "0.12.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbc931937e6ca3a06e3b6c0aa7841849b160a90351d6ab467a8b9b9959767531" +dependencies = [ + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-tls", + "hyper-util", + "js-sys", + "log", + "mime", + "native-tls", + "percent-encoding", + "pin-project-lite", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-native-tls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "resolv-conf" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95325155c684b1c89f7765e30bc1c42e4a6da51ca513615660cb8a62ef9a88e3" + +[[package]] +name = "rick-and-morty" +version = "0.1.0" +dependencies = [ + "anyhow", + "axum", + "dotenvy", + "futures-util", + "http", + "mongodb", + "once_cell", + "reqwest", + "serde", + "serde_json", + "tokio", + "tower", + "tower-http", + "tracing", + "tracing-log", + "tracing-subscriber", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustc_version_runtime" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dd18cd2bae1820af0b6ad5e54f4a51d0f3fcc53b05f845675074efcc7af071d" +dependencies = [ + "rustc_version", + "semver", +] + +[[package]] +name = "rustix" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +dependencies = [ + "bitflags 2.9.1", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.59.0", +] + +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + +[[package]] +name = "rustls" +version = "0.23.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7160e3e10bf4535308537f3c4e1641468cd0e485175d6163087c0393c7d46643" +dependencies = [ + "once_cell", + "rustls-pki-types", + "rustls-webpki 0.103.3", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.7", +] + +[[package]] +name = "rustls-pki-types" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4a72fe2bcf7a6ac6fd7d0b9e5cb68aeb7d4c0a0271730218b3e92d43b4eb435" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + +[[package]] +name = "rustversion" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a0d197bd2c9dc6e53b84da9556a69ba4cdfab8619eb41a8bd1cc2027a0f6b1d" + +[[package]] +name = "ryu" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" + +[[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 = "schemars" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "schemars" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +dependencies = [ + "dyn-clone", + "ref-cast", + "serde", + "serde_json", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "security-framework" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +dependencies = [ + "bitflags 2.9.1", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" + +[[package]] +name = "serde" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_bytes" +version = "0.11.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8437fd221bde2d4ca316d61b90e337e9e702b3820b87d63caa9ba6c02bd06d96" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.219" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "serde_json" +version = "1.0.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" +dependencies = [ + "indexmap 2.10.0", + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59fab13f937fa393d08645bf3a84bdfe86e296747b506ada67bb15f10f218b2a" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_with" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +dependencies = [ + "base64 0.22.1", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.10.0", + "schemars 0.9.0", + "schemars 1.0.4", + "serde", + "serde_derive", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "signal-hook-registry" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" +dependencies = [ + "libc", +] + +[[package]] +name = "slab" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04dc19736151f35336d325007ac991178d504a119863a2fcb3758cdb5e52c50d" + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.104" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "system-configuration" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +dependencies = [ + "bitflags 2.9.1", + "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 = "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" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" + +[[package]] +name = "tempfile" +version = "3.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +dependencies = [ + "fastrand", + "getrandom 0.3.3", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "thread_local" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "time" +version = "0.3.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" + +[[package]] +name = "time-macros" +version = "0.2.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" +dependencies = [ + "num-conv", + "time-core", +] + +[[package]] +name = "tiny-keccak" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" +dependencies = [ + "crunchy", +] + +[[package]] +name = "tinystr" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.46.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17" +dependencies = [ + "backtrace", + "bytes", + "io-uring", + "libc", + "mio", + "pin-project-lite", + "signal-hook-registry", + "slab", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[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.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +dependencies = [ + "rustls 0.23.28", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" +dependencies = [ + "bytes", + "futures-core", + "futures-io", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.1", + "bytes", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "iri-string", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "tracing-core" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +dependencies = [ + "once_cell", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" +dependencies = [ + "log", + "once_cell", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" +dependencies = [ + "matchers", + "nu-ansi-term", + "once_cell", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[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.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" + +[[package]] +name = "unicase" +version = "2.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" + +[[package]] +name = "unicode-bidi" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5" + +[[package]] +name = "unicode-ident" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-properties" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" + +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + +[[package]] +name = "url" +version = "2.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" +dependencies = [ + "getrandom 0.3.3", + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "valuable" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "wasi" +version = "0.14.2+wasi-0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" +dependencies = [ + "wit-bindgen-rt", +] + +[[package]] +name = "wasm-bindgen" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" +dependencies = [ + "cfg-if", + "once_cell", + "rustversion", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" +dependencies = [ + "bumpalo", + "log", + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" +dependencies = [ + "cfg-if", + "js-sys", + "once_cell", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.100" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "web-sys" +version = "0.3.77" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + +[[package]] +name = "widestring" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7cf3379ca1aac9eea11fba24fd7e315d621f8dfe35c8d7d2be8b793726e07d" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + +[[package]] +name = "windows-registry" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +dependencies = [ + "windows-link", + "windows-result", + "windows-strings", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[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 = "wit-bindgen-rt" +version = "0.39.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" +dependencies = [ + "bitflags 2.9.1", +] + +[[package]] +name = "writeable" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" + +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + +[[package]] +name = "yoke" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] + +[[package]] +name = "zerofrom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", + "synstructure", +] + +[[package]] +name = "zeroize" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" + +[[package]] +name = "zerotrie" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a05eb080e015ba39cc9e23bbe5e7fb04d5fb040350f99f34e338d5fdd294428" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.104", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8821bfa --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "rick-and-morty" +version = "0.1.0" +edition = "2024" + +[dependencies] +anyhow = "1.0.98" +axum = { version = "0.8.4", features = ["macros"] } +dotenvy = "0.15.7" +futures-util = "0.3.31" +http = "1.3.1" +mongodb = "3.2.4" +once_cell = "1.21.3" +reqwest = { version = "0.12.22", features = ["json"] } +serde = { version = "1.0.219", features = ["derive"] } +serde_json = "1.0.140" +tokio = { version = "1.46.1", features = [] } +tower = { version = "0.5.2", features = ["util"] } +tower-http = { version = "0.6.6", features = ["cors", "fs", "trace"] } +tracing = "0.1.41" +tracing-log = "0.2.0" +tracing-subscriber = { version = "0.3.19", features = ["env-filter", "fmt"] } diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..3b9629f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM node:latest AS frontend-builder +WORKDIR /app +COPY frontend/package*.json ./ +RUN npm install +COPY frontend/ ./ +RUN npm run build + +FROM rust:1.87-slim AS backend-builder +WORKDIR /app +RUN apt-get update && \ + apt-get install -y pkg-config libssl-dev build-essential ca-certificates + +COPY src/ src/ +COPY Cargo.toml Cargo.lock ./ +RUN cargo build --release + +FROM debian:bookworm-slim +WORKDIR /app +RUN apt-get update && apt-get install -y ca-certificates openssl && rm -rf /var/lib/apt/lists/* +COPY --from=backend-builder /app/target/release/rick-and-morty . +COPY --from=frontend-builder /app/dist ./frontend/dist +EXPOSE 8000 + +CMD ["./rick-and-morty"] \ No newline at end of file diff --git a/compose.yml b/compose.yml new file mode 100644 index 0000000..a85dc4a --- /dev/null +++ b/compose.yml @@ -0,0 +1,26 @@ +services: + mongo: + image: mongo:6.0 + container_name: rick_and_morty_mongo + restart: unless-stopped + ports: + - "27017:27017" + environment: + MONGO_INITDB_DATABASE: rick_and_morty + volumes: + - mongo-data:/data/db + app: + build: . + container_name: rick_and_morty_app + depends_on: + - mongo + environment: + MONGODB_URI: mongodb://mongo:27017 + DB_NAME: rick_and_morty + BIND_ADDR: 0.0.0.0:8000 + ports: + - "8000:8000" + restart: unless-stopped + +volumes: + mongo-data: diff --git a/frontend/.gitignore b/frontend/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/frontend/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/frontend/README.md b/frontend/README.md new file mode 100644 index 0000000..7959ce4 --- /dev/null +++ b/frontend/README.md @@ -0,0 +1,69 @@ +# React + TypeScript + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: + +```js +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + + // Remove tseslint.configs.recommended and replace with this + ...tseslint.configs.recommendedTypeChecked, + // Alternatively, use this for stricter rules + ...tseslint.configs.strictTypeChecked, + // Optionally, add this for stylistic rules + ...tseslint.configs.stylisticTypeChecked, + + // Other configs... + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` + +You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: + +```js +// eslint.config.js +import reactX from 'eslint-plugin-react-x' +import reactDom from 'eslint-plugin-react-dom' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + // Other configs... + // Enable lint rules for React + reactX.configs['recommended-typescript'], + // Enable lint rules for React DOM + reactDom.configs.recommended, + ], + languageOptions: { + parserOptions: { + project: ['./tsconfig.node.json', './tsconfig.app.json'], + tsconfigRootDir: import.meta.dirname, + }, + // other options... + }, + }, +]) +``` diff --git a/frontend/bun.lockb b/frontend/bun.lockb new file mode 100755 index 0000000000000000000000000000000000000000..976b69b8e5c17e0b287cce370be3a07981860960 GIT binary patch literal 99074 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 RE_E~P3J!BD?f=66{2x8H9Mk{+ literal 0 HcmV?d00001 diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js new file mode 100644 index 0000000..d94e7de --- /dev/null +++ b/frontend/eslint.config.js @@ -0,0 +1,23 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import tseslint from 'typescript-eslint' +import { globalIgnores } from 'eslint/config' + +export default tseslint.config([ + globalIgnores(['dist']), + { + files: ['**/*.{ts,tsx}'], + extends: [ + js.configs.recommended, + tseslint.configs.recommended, + reactHooks.configs['recommended-latest'], + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + }, + }, +]) diff --git a/frontend/index.html b/frontend/index.html new file mode 100644 index 0000000..b2b9cab --- /dev/null +++ b/frontend/index.html @@ -0,0 +1,13 @@ + + + + + + + Rick and Morty Tournament + + +
+ + + diff --git a/frontend/package.json b/frontend/package.json new file mode 100644 index 0000000..06294db --- /dev/null +++ b/frontend/package.json @@ -0,0 +1,31 @@ +{ + "name": "frontend", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "tsc -b && vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "@tailwindcss/vite": "^4.1.11", + "react": "^19.1.0", + "react-dom": "^19.1.0", + "tailwindcss": "^4.1.11" + }, + "devDependencies": { + "@eslint/js": "^9.30.1", + "@types/react": "^19.1.8", + "@types/react-dom": "^19.1.6", + "@vitejs/plugin-react-swc": "^3.10.2", + "eslint": "^9.30.1", + "eslint-plugin-react-hooks": "^5.2.0", + "eslint-plugin-react-refresh": "^0.4.20", + "globals": "^16.3.0", + "typescript": "~5.8.3", + "typescript-eslint": "^8.35.1", + "vite": "^7.0.3" + } +} diff --git a/frontend/public/favicon.ico b/frontend/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..c7a080182708b7406a82eba6810a84cf15b03c41 GIT binary patch literal 15951 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 literal 0 HcmV?d00001 diff --git a/frontend/public/morty.png b/frontend/public/morty.png new file mode 100644 index 0000000000000000000000000000000000000000..b230308e6c0c85f0664b25161efdc1272659e616 GIT binary patch literal 22290 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 literal 0 HcmV?d00001 diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx new file mode 100644 index 0000000..13f8ded --- /dev/null +++ b/frontend/src/App.tsx @@ -0,0 +1,137 @@ +// src/App.tsx +import React, { useEffect, useState } from "react"; +import { getCharacters, rateCharacters } from "./api"; +import type { Character } from "./types"; +import { Card } from "./components/card"; +import { Table } from "./components/table"; +import { getId } from "./utils"; + +function getRandomIndex(length: number) { + return Math.floor(Math.random() * length); +} + +function getRandomPair(characters: Character[], lastPair: [number, number]) { + if (characters.length < 2) return [null, null]; + + let firstIndex = getRandomIndex(characters.length); + let secondIndex = getRandomIndex(characters.length); + + while ( + firstIndex === lastPair[0] || + secondIndex === lastPair[1] || + firstIndex === secondIndex + ) { + firstIndex = getRandomIndex(characters.length); + secondIndex = getRandomIndex(characters.length); + } + return [characters[firstIndex], characters[secondIndex]]; +} + +const App: React.FC = () => { + const [characters, setCharacters] = useState([]); + const [rivals, setRivals] = useState<[Character | null, Character | null]>([ + null, + null, + ]); + const [voting, setVoting] = useState(false); + const [, setVotedLeft] = useState(false); + const [skipped, setSkipped] = useState(false); + const [lastPair] = useState<[number, number]>([0, 0]); + const currentYear = new Date().getFullYear(); + + useEffect(() => { + (async () => { + const chars = await getCharacters(); + setCharacters(chars); + const [first, second] = getRandomPair(chars, lastPair); + setRivals([first, second]); + })(); + }, []); + + const generateNewRivals = () => { + const [first, second] = getRandomPair(characters, lastPair); + setRivals([first, second]); + }; + + const handleVote = async (winnerIdx: 0 | 1, loserIdx: 0 | 1) => { + if (voting || !rivals[winnerIdx] || !rivals[loserIdx]) return; + setVoting(true); + setVotedLeft(winnerIdx === 0); + const winnerId = getId(rivals[winnerIdx]); + const loserId = getId(rivals[loserIdx]); + if (!winnerId || !loserId) return; + await rateCharacters(winnerId, loserId); + const chars = await getCharacters(); + setCharacters(chars); + setTimeout(() => { + setVoting(false); + generateNewRivals(); + }, 1000); + }; + + const handleSkip = () => { + setSkipped(true); + setTimeout(() => { + setSkipped(false); + generateNewRivals(); + }, 1000); + }; + + return ( +
+

Rick & Morty

+

Tournament

+
+

+ How does it work? +

+

+ Below there are two cards with two characters. +

+

+ Choose whichever character you like better. +

+

Enjoy!

+
+ {/* Loader can be added here */} +
+ {rivals[0] && ( + handleVote(0, 1)} + isRight={false} + /> + )} + {rivals[1] && ( + handleVote(1, 0)} + isRight={true} + /> + )} +
+ {rivals[0] && ( + <> + +

Top 10

+ + + )} + +

+ Copyright {currentYear} Gabriel Kaszewski +

+ + ); +}; + +export default App; diff --git a/frontend/src/api.ts b/frontend/src/api.ts new file mode 100644 index 0000000..4f92e31 --- /dev/null +++ b/frontend/src/api.ts @@ -0,0 +1,14 @@ +import type { Character } from './types'; + +export const getCharacters = async (): Promise => { + const res = await fetch('/characters'); + return res.json(); +}; + +export const rateCharacters = async (winnerId: string, loserId: string) => { + await fetch('/rate', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ winner_id: winnerId, loser_id: loserId }), + }); +}; diff --git a/frontend/src/components/card.tsx b/frontend/src/components/card.tsx new file mode 100644 index 0000000..f503f4b --- /dev/null +++ b/frontend/src/components/card.tsx @@ -0,0 +1,62 @@ +import React from 'react'; +import type { Character } from '../types'; + +interface CardProps { + data: Character; + isClicked?: boolean; + skipped?: boolean; + onClick?: () => void; + isRight?: boolean; +} + +export const Card: React.FC = ({ + data, + isClicked, + skipped, + onClick, +}) => ( +
+
+ {/* FRONT */} +
+

{data.name}

+ {data.name} +

Info

+
+
+ + + + + + + + + + + + + + + + + + + + + + +
Species{data.species}
Gender{data.gender}
Status{data.status}
Origin{data.origin.name}
Last location{data.location.name}
+
+ + {/* BACK */} +
+ {/* You can put whatever you want here, like a background or extra info */} +
+ + +); diff --git a/frontend/src/components/table-element.tsx b/frontend/src/components/table-element.tsx new file mode 100644 index 0000000..74f0190 --- /dev/null +++ b/frontend/src/components/table-element.tsx @@ -0,0 +1,10 @@ +// src/components/TableElement.tsx +import React from 'react'; +import type { Character } from '../types'; + +export const TableElement: React.FC<{ character: Character }> = ({ character }) => ( +
+ {character.name} +

{character.name}

+
+); \ No newline at end of file diff --git a/frontend/src/components/table.tsx b/frontend/src/components/table.tsx new file mode 100644 index 0000000..5c1c92f --- /dev/null +++ b/frontend/src/components/table.tsx @@ -0,0 +1,11 @@ +import React from 'react'; +import type { Character } from '../types'; +import { TableElement } from './table-element'; + +export const Table: React.FC<{ characters: Character[] }> = ({ characters }) => ( +
+ {characters.map((character) => ( + + ))} +
+); diff --git a/frontend/src/index.css b/frontend/src/index.css new file mode 100644 index 0000000..94b94c6 --- /dev/null +++ b/frontend/src/index.css @@ -0,0 +1,42 @@ +@import "tailwindcss"; + +.card { + height: 470px; + width: 300px; + perspective: 1000px; +} + +.card-inner { + position: relative; + width: 100%; + height: 100%; + transition: transform 0.8s; + transform-style: preserve-3d; +} + +.flip-card .card-inner { + transform: rotateY(180deg); +} + +.card-front, .card-back { + position: absolute; + width: 100%; + height: 100%; + backface-visibility: hidden; +} + +.card-back { + transform: rotateY(180deg); + background-image: url("/morty.png"); /* Adjust path as needed */ + background-position: center; + background-size: contain; + background-repeat: no-repeat; + display: flex; + align-items: center; + justify-content: center; +} + +.avatar { + width: 150px; + height: 150px; +} diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx new file mode 100644 index 0000000..bef5202 --- /dev/null +++ b/frontend/src/main.tsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.tsx' + +createRoot(document.getElementById('root')!).render( + + + , +) diff --git a/frontend/src/types.ts b/frontend/src/types.ts new file mode 100644 index 0000000..cc39132 --- /dev/null +++ b/frontend/src/types.ts @@ -0,0 +1,21 @@ +export interface OriginOrLocation { + name: string; + url: string; +} + +export interface Character { + _id: string | { $oid: string }; + rmid: number; + name: string; + status: string; + species: string; + type: string; + gender: string; + origin: OriginOrLocation; + location: OriginOrLocation; + image: string; + episode: string[]; + url: string; + created: string; + elo_rating: number; +} diff --git a/frontend/src/utils.ts b/frontend/src/utils.ts new file mode 100644 index 0000000..292b1d9 --- /dev/null +++ b/frontend/src/utils.ts @@ -0,0 +1,9 @@ +import type { Character } from "./types"; + +export function getId(character: Character | null) { + if (!character) return undefined; + const id = character._id as string | { $oid: string } | undefined; + if (typeof id === 'string') return id; + if (id && typeof id.$oid === 'string') return id.$oid; + return undefined; +} \ No newline at end of file diff --git a/frontend/src/vite-env.d.ts b/frontend/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/frontend/src/vite-env.d.ts @@ -0,0 +1 @@ +/// diff --git a/frontend/tsconfig.app.json b/frontend/tsconfig.app.json new file mode 100644 index 0000000..227a6c6 --- /dev/null +++ b/frontend/tsconfig.app.json @@ -0,0 +1,27 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo", + "target": "ES2022", + "useDefineForClassFields": true, + "lib": ["ES2022", "DOM", "DOM.Iterable"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + "jsx": "react-jsx", + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["src"] +} diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json new file mode 100644 index 0000000..1ffef60 --- /dev/null +++ b/frontend/tsconfig.json @@ -0,0 +1,7 @@ +{ + "files": [], + "references": [ + { "path": "./tsconfig.app.json" }, + { "path": "./tsconfig.node.json" } + ] +} diff --git a/frontend/tsconfig.node.json b/frontend/tsconfig.node.json new file mode 100644 index 0000000..f85a399 --- /dev/null +++ b/frontend/tsconfig.node.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo", + "target": "ES2023", + "lib": ["ES2023"], + "module": "ESNext", + "skipLibCheck": true, + + /* Bundler mode */ + "moduleResolution": "bundler", + "allowImportingTsExtensions": true, + "verbatimModuleSyntax": true, + "moduleDetection": "force", + "noEmit": true, + + /* Linting */ + "strict": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "erasableSyntaxOnly": true, + "noFallthroughCasesInSwitch": true, + "noUncheckedSideEffectImports": true + }, + "include": ["vite.config.ts"] +} diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts new file mode 100644 index 0000000..fb4d238 --- /dev/null +++ b/frontend/vite.config.ts @@ -0,0 +1,8 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react-swc' +import tailwindcss from '@tailwindcss/vite' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react(), tailwindcss()], +}) diff --git a/src/bin/fetch_characters.rs b/src/bin/fetch_characters.rs new file mode 100644 index 0000000..01f4330 --- /dev/null +++ b/src/bin/fetch_characters.rs @@ -0,0 +1,127 @@ +use mongodb::{ + Client, + bson::{doc, to_document}, + options::UpdateOptions, +}; +use reqwest::Client as HttpClient; +use rick_and_morty::models::{Character, OriginOrLocation}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Deserialize, Serialize)] +struct ApiCharacter { + id: i32, + name: String, + status: String, + species: String, + #[serde(rename = "type")] + character_type: String, + gender: String, + origin: OriginOrLocation, + location: OriginOrLocation, + image: String, + episode: Vec, + url: String, + created: String, +} + +impl From for Character { + fn from(api: ApiCharacter) -> Self { + Character { + id: None, // always None for new/incoming data + rmid: api.id, + name: api.name, + status: api.status, + species: api.species, + r#type: api.character_type, + gender: api.gender, + origin: api.origin, + location: api.location, + image: api.image, + episode: api.episode, + url: api.url, + created: api.created, + elo_rating: 1000.0, + } + } +} + +fn init_tracing() { + use tracing_subscriber::EnvFilter; + tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .with_target(true) + .with_level(true) + .init(); +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + init_tracing(); + dotenvy::dotenv().ok(); + let db_uri = + std::env::var("MONGODB_URI").unwrap_or_else(|_| "mongodb://localhost:27017".to_string()); + let db_name = std::env::var("DB_NAME").unwrap_or_else(|_| "rick_and_morty".to_string()); + + let client = Client::with_uri_str(&db_uri).await?; + let db = client.database(&db_name); + let collection = db.collection::("characters"); + + tracing::info!("Starting to fetch characters from Rick and Morty API"); + let http = HttpClient::new(); + + let mut all_characters: Vec = Vec::new(); + let mut next_url = "https://rickandmortyapi.com/api/character".to_string(); + + while !next_url.is_empty() { + tracing::info!(url = %next_url, "Fetching page"); + let resp = http + .get(&next_url) + .send() + .await? + .json::() + .await?; + let results = resp["results"].as_array().unwrap(); + for c in results { + let c: ApiCharacter = serde_json::from_value(c.clone()).unwrap(); + all_characters.push(c.into()); + } + next_url = resp["info"]["next"].as_str().unwrap_or("").to_string(); + } + + tracing::info!( + count = all_characters.len(), + "Fetched all characters, starting DB upsert" + ); + let options = UpdateOptions::builder().upsert(true).build(); + // let insert_result = collection.insert_many(all_characters.clone()).await?; + + for character in &all_characters { + let filter = doc! { "rmid": character.rmid }; + let mut set_doc = to_document(character)?; + set_doc.remove("elo_rating"); // Do NOT overwrite existing Elo + let update = doc! { + "$set": set_doc, + "$setOnInsert": { "elo_rating": 1000.0 } + }; + if let Err(e) = collection + .update_one(filter, update) + .with_options(Some(options.clone())) + .await + { + tracing::error!(error = ?e, id = character.rmid, name = %character.name, "Failed to upsert character"); + } + tracing::info!(id = character.rmid, name = %character.name, "Upserted character"); + } + + // tracing::info!("Inserted {} characters", insert_result.inserted_ids.len()); + + let character_count = collection.count_documents(doc! {}).await?; + tracing::info!( + count = character_count, + "Total characters in DB after import" + ); + + tracing::info!("Done! Imported/updated characters."); + + Ok(()) +} diff --git a/src/db.rs b/src/db.rs new file mode 100644 index 0000000..b01b0ff --- /dev/null +++ b/src/db.rs @@ -0,0 +1,11 @@ +use mongodb::{Client, Database}; +use once_cell::sync::OnceCell; + +pub static DB: OnceCell = OnceCell::new(); + +pub async fn connect_db(uri: &str, db_name: &str) -> mongodb::error::Result<()> { + let client = Client::with_uri_str(uri).await?; + let db = client.database(db_name); + DB.set(db).ok(); + Ok(()) +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..7896840 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,4 @@ +pub mod db; +pub mod models; +pub mod routes; +pub mod utils; diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a0a2bb9 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,59 @@ +use axum::{ + Router, + routing::{get, post}, +}; +use http::Method; +use rick_and_morty::{db, routes}; +use tower_http::{ + cors::{Any, CorsLayer}, + services::ServeDir, + trace::TraceLayer, +}; + +fn init_tracing() { + use tracing_subscriber::EnvFilter; + tracing_subscriber::fmt() + .with_env_filter(EnvFilter::from_default_env()) + .with_target(true) + .with_level(true) + .init(); +} + +#[tokio::main] +async fn main() { + init_tracing(); + dotenvy::dotenv().ok(); + + let db_uri = std::env::var("MONGODB_URI").expect("MONGODB_URI not set"); + let db_name = std::env::var("DB_NAME").unwrap_or_else(|_| "rick_and_morty".to_string()); + let address = std::env::var("BIND_ADDR").unwrap_or_else(|_| "0.0.0.0:8000".to_string()); + + db::connect_db(&db_uri, &db_name) + .await + .expect("Failed to connect to database"); + + let db = db::DB.get().expect("Database not initialized"); + + let cors = CorsLayer::new() + // allow `GET` and `POST` when accessing the resource + .allow_methods([Method::GET, Method::POST, Method::OPTIONS]) + .allow_headers([http::header::CONTENT_TYPE]) + // allow requests from any origin + .allow_origin(Any); + + let app = Router::new() + .route("/characters", get(routes::get_characters)) + .route("/rate", post(routes::rate)) + .with_state(db.clone()) + .layer(TraceLayer::new_for_http()) + .layer(cors) + .fallback_service(ServeDir::new("frontend/dist").append_index_html_on_directories(true)); + + let listener = tokio::net::TcpListener::bind(address) + .await + .expect("Failed to bind address"); + + println!("Listening on {}", listener.local_addr().unwrap()); + + axum::serve(listener, app).await.unwrap(); +} diff --git a/src/models/mod.rs b/src/models/mod.rs new file mode 100644 index 0000000..16614a2 --- /dev/null +++ b/src/models/mod.rs @@ -0,0 +1,27 @@ +use mongodb::bson::{doc, oid::ObjectId}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct OriginOrLocation { + pub name: String, + pub url: String, +} + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Character { + #[serde(rename = "_id", skip_serializing_if = "Option::is_none")] + pub id: Option, // Mongo _id + pub rmid: i32, // Rick&Morty ID, don't confuse with _id + pub name: String, + pub status: String, + pub species: String, + pub r#type: String, + pub gender: String, + pub origin: OriginOrLocation, + pub location: OriginOrLocation, + pub image: String, + pub episode: Vec, + pub url: String, + pub created: String, + pub elo_rating: f64, +} diff --git a/src/routes/mod.rs b/src/routes/mod.rs new file mode 100644 index 0000000..203db4b --- /dev/null +++ b/src/routes/mod.rs @@ -0,0 +1,125 @@ +use axum::response::Html; +use axum::{Json, extract::State, http::StatusCode}; +use futures_util::stream::TryStreamExt; +use mongodb::Database; +use mongodb::bson::doc; +use mongodb::bson::oid::ObjectId; +use serde::{Deserialize, Serialize}; + +use crate::models::Character; +use crate::utils::calculate_elo; + +#[derive(Deserialize)] +pub struct RateRequest { + winner_id: String, + loser_id: String, +} + +#[derive(Deserialize, Serialize)] +pub struct RateResponse { + winner: Character, + loser: Character, +} + +static K_FACTOR: f64 = 32.0; // K-factor for Elo rating system + +pub async fn get_characters( + State(db): State, +) -> Result>, StatusCode> { + let collection = db.collection::("characters"); + let pipeline = vec![doc! { "$sort": { "elo_rating": -1 } }]; + + let mut cursor = collection + .aggregate(pipeline) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + let mut characters = Vec::new(); + while let Some(result) = cursor + .try_next() + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + { + let character: Character = + mongodb::bson::from_document(result).map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + characters.push(character); + } + + tracing::info!(count = characters.len(), "Fetched characters from DB"); + + Ok(Json(characters)) +} + +#[axum::debug_handler] +pub async fn rate( + State(db): State, + Json(req): Json, +) -> Result, StatusCode> { + let collection = db.collection::("characters"); + + let winner_oid = ObjectId::parse_str(&req.winner_id).map_err(|_| StatusCode::BAD_REQUEST)?; + let loser_oid = ObjectId::parse_str(&req.loser_id).map_err(|_| StatusCode::BAD_REQUEST)?; + + let winner = collection + .find_one(doc! { "_id": winner_oid }) + .await + .ok() + .flatten() + .ok_or(StatusCode::NOT_FOUND)?; + let loser = collection + .find_one(doc! { "_id": loser_oid }) + .await + .ok() + .flatten() + .ok_or(StatusCode::NOT_FOUND)?; + + let (new_winner_elo, new_loser_elo) = + calculate_elo(winner.elo_rating, loser.elo_rating, K_FACTOR); + + collection + .update_one( + doc! {"_id": &winner_oid}, + doc! { "$set": { "elo_rating": new_winner_elo } }, + ) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + collection + .update_one( + doc! {"_id": &loser_oid}, + doc! { "$set": { "elo_rating": new_loser_elo } }, + ) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)?; + + // return resposnse with characters' new Elo ratings + let updated_winner = collection + .find_one(doc! { "_id": winner_oid }) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .ok_or(StatusCode::NOT_FOUND)?; + let updated_loser = collection + .find_one(doc! { "_id": loser_oid }) + .await + .map_err(|_| StatusCode::INTERNAL_SERVER_ERROR)? + .ok_or(StatusCode::NOT_FOUND)?; + + tracing::info!( + "Rated characters: winner_id = {}, loser_id = {}, new_winner_elo = + {}, new_loser_elo = {}", + req.winner_id, + req.loser_id, + new_winner_elo, + new_loser_elo + ); + + Ok(Json(RateResponse { + winner: updated_winner, + loser: updated_loser, + })) +} + +pub async fn index() -> Html<&'static str> { + tracing::info!("Serving index page"); + Html("

Welcome to the Rick and Morty Character Rating API

") +} diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..2cb77f1 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,9 @@ +pub fn calculate_elo(winner_elo: f64, loser_elo: f64, k_factor: f64) -> (f64, f64) { + let expected_winner = 1.0 / (1.0 + 10f64.powf((loser_elo - winner_elo) / 400.0)); + let expected_loser = 1.0 / (1.0 + 10f64.powf((winner_elo - loser_elo) / 400.0)); + + let new_winner_elo = winner_elo + k_factor * (1.0 - expected_winner); + let new_loser_elo = loser_elo + k_factor * (0.0 - expected_loser); + + (new_winner_elo, new_loser_elo) +}