diff --git a/.env-sample b/.env-sample index bd39300d..d99b6965 100644 --- a/.env-sample +++ b/.env-sample @@ -12,9 +12,8 @@ SERVER_PORT=8080 TESTNET=true # Tesnet bootstrap IP:PORT BOOTSTRAP=127.0.0.1:6881 -HOMESERVER= -# Needed for event streams. Should not be needed once PubkyClient is upgraded to return http URLs -HOMESERVER_URL=http://localhost:6287 +# Homeserver ID. Needed for event streams. +HOMESERVER= # Maximum number of events to fetch at once from a homeserver EVENTS_LIMIT=1000 # Sleep between checks to homeserver diff --git a/Cargo.lock b/Cargo.lock index afa758ff..49b9bb04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,18 +4,18 @@ version = 4 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "aead" @@ -59,9 +59,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -74,36 +74,37 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e" dependencies = [ "anstyle", - "windows-sys", + "once_cell", + "windows-sys 0.59.0", ] [[package]] @@ -114,9 +115,9 @@ checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04" [[package]] name = "arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" +checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" dependencies = [ "derive_arbitrary", ] @@ -141,9 +142,9 @@ dependencies = [ [[package]] name = "arrayref" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d151e35f61089500b617991b791fc8bfd237ae50cd5950803758a179b41e67a" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" @@ -159,7 +160,7 @@ checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -179,9 +180,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "axum" @@ -220,11 +221,11 @@ dependencies = [ [[package]] name = "axum" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d6fd624c75e18b3b4c6b9caf42b1afe24437daaee904069137d8bab077be8b8" +checksum = "efea76243612a2436fb4074ba0cf3ba9ea29efdeb72645d8fc63f116462be1de" dependencies = [ - "axum-core 0.5.0", + "axum-core 0.5.1", "bytes", "form_urlencoded", "futures-util", @@ -275,12 +276,12 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df1362f362fd16024ae199c1970ce98f9661bf5ef94b9808fee734bc3698b733" +checksum = "eab1b0df7cded837c40dacaa2e1c33aa17c84fc3356ae67b5645f1e83190753e" dependencies = [ "bytes", - "futures-util", + "futures-core", "http", "http-body", "http-body-util", @@ -295,27 +296,28 @@ dependencies = [ [[package]] name = "axum-extra" -version = "0.9.3" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be6ea09c9b96cb5076af0de2e383bd2bc0c18f827cf1967bdd353e0b910d733" +checksum = "c794b30c904f0a1c2fb7740f7df7f7972dfaa14ef6f57cb6178dc63e5dca2f04" dependencies = [ "axum 0.7.9", "axum-core 0.4.5", "bytes", + "fastrand", "futures-util", "headers", "http", "http-body", "http-body-util", "mime", + "multer", "pin-project-lite", "serde", "tokio", "tokio-util", - "tower 0.4.13", + "tower 0.5.2", "tower-layer", "tower-service", - "tracing", ] [[package]] @@ -326,7 +328,31 @@ checksum = "57d123550fa8d071b7255cb0cc04dc302baa6c8c4a79f55701552684d8399bce" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", +] + +[[package]] +name = "axum-server" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56bac90848f6a9393ac03c63c640925c4b7c8ca21654de40d53f55964667c7d8" +dependencies = [ + "arc-swap", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "pin-project-lite", + "rustls", + "rustls-pemfile", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower 0.4.13", + "tower-service", ] [[package]] @@ -345,17 +371,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets", ] [[package]] @@ -393,9 +419,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.6.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" dependencies = [ "serde", ] @@ -445,9 +471,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" dependencies = [ "serde", ] @@ -460,9 +486,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.1.14" +version = "1.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d2eb3cd3d1bf4529e31c215ee6f93ec5a3d536d9f578f93d9d33ee19562932" +checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" dependencies = [ "shlex", ] @@ -473,6 +499,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.39" @@ -481,10 +513,8 @@ checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", - "js-sys", "num-traits", "serde", - "wasm-bindgen", "windows-targets", ] @@ -550,9 +580,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.13" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" +checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" dependencies = [ "clap_builder", "clap_derive", @@ -560,9 +590,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.13" +version = "4.5.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" +checksum = "1b26884eb4b57140e4d2d93652abfa49498b938b3c9179f9fc487b0acc3edad7" dependencies = [ "anstream", "anstyle", @@ -572,21 +602,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "cobs" @@ -596,9 +626,9 @@ checksum = "67ba02a97a2bd10f4b59b25c7973101c79642302776489e030cd13cdab09ed15" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" @@ -614,6 +644,17 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "console_log" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be8aed40e4edbf4d3b4431ab260b63fdc40f5780a4766824329ea0f1eefe3c0f" +dependencies = [ + "log", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -659,12 +700,13 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.21.0" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4934e6b7e8419148b6ef56950d277af8561060b56afd59e2aadf98b59fce6baa" +checksum = "2eac901828f88a5241ee0600950ab981148a18f2f756900ffba1b125ca6a3ef9" dependencies = [ "cookie", - "idna 0.5.0", + "document-features", + "idna", "log", "publicsuffix", "serde", @@ -686,15 +728,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" dependencies = [ "libc", ] @@ -736,7 +778,7 @@ dependencies = [ "criterion-plot", "futures", "is-terminal", - "itertools 0.10.5", + "itertools", "num-traits", "once_cell", "oorandom", @@ -758,20 +800,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b50826342786a51a89e2da3a28f1c32b06e387201bc2d19791f622c673706b1" dependencies = [ "cast", - "itertools 0.10.5", + "itertools", ] [[package]] name = "critical-section" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f64009896348fc5af4222e9cf7d7d82a95a256c634ebcf61c53e4ea461422242" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" [[package]] name = "crossbeam-deque" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" dependencies = [ "crossbeam-epoch", "crossbeam-utils", @@ -788,18 +830,18 @@ dependencies = [ [[package]] name = "crossbeam-queue" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] name = "crunchy" @@ -857,7 +899,20 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] @@ -911,13 +966,13 @@ dependencies = [ [[package]] name = "derive_arbitrary" -version = "1.3.2" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" +checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -960,7 +1015,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -1039,18 +1094,18 @@ checksum = "edd0f118536f44f5ccd48bcb8b111bdc3de888b58c74639dfb034a357d0f206d" [[package]] name = "encoding_rs" -version = "0.8.34" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] [[package]] name = "env_filter" -version = "0.1.0" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a009aa4810eb158359dda09d0c87378e4bbb89b5a801f016885a4707ba24f7ea" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" dependencies = [ "log", "regex", @@ -1077,19 +1132,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fiat-crypto" @@ -1099,9 +1154,9 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -1109,9 +1164,9 @@ dependencies = [ [[package]] name = "flume" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ "futures-core", "futures-sink", @@ -1149,11 +1204,21 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "forwarded-header-value" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835f84f38484cc86f110a805655697908257fb9a7af005234060891557198e9" +dependencies = [ + "nonempty", + "thiserror 1.0.69", +] + [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -1166,9 +1231,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -1176,15 +1241,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -1193,38 +1258,57 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-lite" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "f5edaec856126859abb19ed65f39e90fea3a9574b9707f13539acf4abf7eb532" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] [[package]] name = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-timer" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1238,6 +1322,22 @@ dependencies = [ "slab", ] +[[package]] +name = "genawaiter" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c86bd0361bcbde39b13475e6e36cb24c329964aa2611be285289d1e4b751c1a0" +dependencies = [ + "futures-core", + "genawaiter-macro", +] + +[[package]] +name = "genawaiter-macro" +version = "0.99.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b32dfe1fdfc0bbde1f22a5da25355514b5e450c33a6af6770884c8750aedfbc" + [[package]] name = "generic-array" version = "0.14.7" @@ -1264,15 +1364,35 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "governor" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" +dependencies = [ + "cfg-if", + "dashmap", + "futures", + "futures-timer", + "no-std-compat", + "nonzero_ext", + "parking_lot", + "portable-atomic", + "quanta", + "rand", + "smallvec", + "spinning_top", +] [[package]] name = "h2" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" +checksum = "ccae279728d634d083c00f6099cb58f01cc99c145b84b8be2f6c74618d79922e" dependencies = [ "atomic-waker", "bytes", @@ -1312,6 +1432,12 @@ version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "headers" version = "0.4.0" @@ -1365,7 +1491,25 @@ dependencies = [ "bitflags", "byteorder", "heed-traits", - "heed-types", + "heed-types 0.20.1", + "libc", + "lmdb-master-sys", + "once_cell", + "page_size", + "synchronoise", + "url", +] + +[[package]] +name = "heed" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd54745cfacb7b97dee45e8fdb91814b62bccddb481debb7de0f9ee6b7bf5b43" +dependencies = [ + "bitflags", + "byteorder", + "heed-traits", + "heed-types 0.21.0", "libc", "lmdb-master-sys", "once_cell", @@ -1386,6 +1530,16 @@ name = "heed-types" version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d3f528b053a6d700b2734eabcd0fd49cb8230647aa72958467527b0b7917114" +dependencies = [ + "byteorder", + "heed-traits", +] + +[[package]] +name = "heed-types" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c255bdf46e07fb840d120a36dcc81f385140d7191c76a7391672675c01a55d" dependencies = [ "bincode", "byteorder", @@ -1400,6 +1554,12 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" + [[package]] name = "hex" version = "0.4.3" @@ -1408,9 +1568,9 @@ checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" [[package]] name = "http" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" dependencies = [ "bytes", "fnv", @@ -1442,15 +1602,29 @@ dependencies = [ [[package]] name = "http-range-header" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + +[[package]] +name = "http-relay" +version = "0.1.0" +source = "git+https://github.com/pubky/pubky?branch=v0.4.0-rc1#30237c43cbd07d472cd5e5b77b64a343d832647e" +dependencies = [ + "anyhow", + "axum 0.7.9", + "axum-server", + "futures-util", + "tokio", + "tracing", + "url", +] [[package]] name = "httparse" -version = "1.9.4" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpc-test" @@ -1481,9 +1655,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "1.4.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" +checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" dependencies = [ "bytes", "futures-channel", @@ -1502,9 +1676,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.2" +version = "0.27.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" +checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2" dependencies = [ "futures-util", "http", @@ -1555,9 +1729,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1691,27 +1865,7 @@ checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", -] - -[[package]] -name = "idna" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", -] - -[[package]] -name = "idna" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" -dependencies = [ - "unicode-bidi", - "unicode-normalization", + "syn 2.0.96", ] [[package]] @@ -1737,12 +1891,12 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.2", "serde", ] @@ -1766,26 +1920,26 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" [[package]] name = "is-terminal" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b" +checksum = "3f187290c0ed3dfe3f7c85bedddd320949b68fc86ca0ceb71adfb05b3dc3af2a" dependencies = [ - "hermit-abi", + "hermit-abi 0.4.0", "libc", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -1796,27 +1950,19 @@ dependencies = [ "either", ] -[[package]] -name = "itertools" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" -dependencies = [ - "either", -] - [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1834,9 +1980,9 @@ checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" @@ -1850,15 +1996,15 @@ dependencies = [ [[package]] name = "linux-raw-sys" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "litemap" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[package]] name = "litrs" @@ -1895,24 +2041,23 @@ checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" [[package]] name = "log" -version = "0.4.22" +version = "0.4.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +checksum = "04cbf5b083de1c7e0222a7a51dbfdba1cbe1c6ab0b15e29fff3f6c077fd9cd9f" [[package]] name = "lru" -version = "0.12.3" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3262e75e648fce39813cb56ac41f3c3e3f65217ebf3844d818d1f9398cfb0dc" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" [[package]] name = "mainline" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b751ffb57303217bcae8f490eee6044a5b40eadf6ca05ff476cad37e7b7970d" +version = "4.2.0" +source = "git+https://github.com/pubky/mainline?branch=v5-rc1#9899b4dd582d53d75f7ada7bde3c345d21fe4f29" dependencies = [ - "bytes", "crc", + "document-features", "ed25519-dalek", "flume", "lru", @@ -1921,7 +2066,7 @@ dependencies = [ "serde_bencode", "serde_bytes", "sha1_smol", - "thiserror 1.0.69", + "thiserror 2.0.11", "tracing", ] @@ -1970,23 +2115,39 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "b8402cab7aefae129c6977bb0ff1b8fd9a04eb5b51efc50a70bea51cda0c7924" dependencies = [ - "adler", + "adler2", ] [[package]] name = "mio" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ - "hermit-abi", "libc", "wasi", - "windows-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", ] [[package]] @@ -2050,9 +2211,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a0d57c55d2d1dc62a2b1d16a0a1079eb78d67c36bdf468d582ab4482ec7002" dependencies = [ "quote", - "syn 2.0.87", + "syn 2.0.96", ] +[[package]] +name = "no-std-compat" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93853da6d84c2e3c7d730d6473e8817692dd89be387eb01b94d7f108ecb5b8c" + +[[package]] +name = "nonempty" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9e591e719385e6ebaeb5ce5d3887f7d5676fceca6411d1925ccc95745f3d6f7" + +[[package]] +name = "nonzero_ext" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38bf9645c8b145698bb0b18a4637dcacbc421ea49bef2317e4fd8065a387cf21" + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -2104,15 +2283,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "object" -version = "0.36.1" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "081b846d1d56ddfc18fdf1a922e4f6e07a11768ea1b92dec44e42b72712ccfce" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] @@ -2137,9 +2316,9 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags", "cfg-if", @@ -2158,7 +2337,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -2169,9 +2348,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -2195,6 +2374,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" + [[package]] name = "parking_lot" version = "0.12.3" @@ -2252,9 +2437,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "phf" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ade2d8b8f33c7333b51bcf0428d37e217e9f32192ae4772156f65063b8ce03dc" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ "phf_macros", "phf_shared", @@ -2262,9 +2447,9 @@ dependencies = [ [[package]] name = "phf_codegen" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8d39688d359e6b34654d328e262234662d16cc0f60ec8dcbe5e718709342a5a" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ "phf_generator", "phf_shared", @@ -2272,9 +2457,9 @@ dependencies = [ [[package]] name = "phf_generator" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e4cc64c2ad9ebe670cb8fd69dd50ae301650392e81c05f9bfcb2d5bdbc24b0" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", "rand", @@ -2282,51 +2467,51 @@ dependencies = [ [[package]] name = "phf_macros" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3444646e286606587e49f3bcf1679b8cef1dc2c5ecc29ddacaffc305180d464b" +checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ "phf_generator", "phf_shared", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "phf_shared" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", ] [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" [[package]] name = "pin-utils" @@ -2336,54 +2521,67 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkarr" -version = "2.2.0" -source = "git+https://github.com/Pubky/pkarr?branch=v3#a40ce2f639811a740326b0a1c4548c8ac67c8865" +version = "3.0.0" +source = "git+https://github.com/pubky/pkarr?branch=v3-rc1#116bd22eb2916cff0cb84cd49d840e83094af65b" dependencies = [ "base32", - "bytes", + "byteorder", "document-features", "dyn-clone", "ed25519-dalek", "flume", "futures", + "futures-lite", + "genawaiter", + "getrandom", + "heed 0.20.5", "js-sys", "lru", "mainline", + "once_cell", + "page_size", + "pubky-timestamp", "rand", + "reqwest", + "rustls", + "rustls-webpki", "self_cell", + "serde", + "sha1_smol", "simple-dns", - "thiserror 1.0.69", + "thiserror 2.0.11", + "tokio", "tracing", - "wasm-bindgen", + "url", "wasm-bindgen-futures", - "web-sys", ] [[package]] -name = "pkarr" -version = "2.2.1-alpha.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b59d10828418841f34089b861b33d966b63ffd34fe770f4bc46df2d8aba118f5" +name = "pkarr-relay" +version = "0.1.0" +source = "git+https://github.com/pubky/pkarr?branch=v3-rc1#116bd22eb2916cff0cb84cd49d840e83094af65b" dependencies = [ - "base32", + "anyhow", + "axum 0.7.9", + "axum-server", "bytes", - "document-features", - "dyn-clone", - "ed25519-dalek", - "flume", - "futures", - "js-sys", - "lru", + "clap", + "dirs-next", + "governor", + "http", + "httpdate", "mainline", - "rand", - "self_cell", + "pkarr", + "pubky-timestamp", + "rustls", "serde", - "simple-dns", - "thiserror 1.0.69", + "thiserror 2.0.11", + "tokio", + "toml", + "tower-http", + "tower_governor", "tracing", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "tracing-subscriber", ] [[package]] @@ -2398,15 +2596,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "plotters" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15b6eccb8484002195a3e44fe65a4ce8e93a625797a063735536fd59cb01cf3" +checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747" dependencies = [ "num-traits", "plotters-backend", @@ -2417,15 +2615,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414cec62c6634ae900ea1c56128dfe87cf63e7caece0852ec76aba307cebadb7" +checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a" [[package]] name = "plotters-svg" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81b30686a7d9c3e010b84284bdd26a29f2138574f52f5eb6f794fc0ad924e705" +checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670" dependencies = [ "plotters-backend", ] @@ -2441,11 +2639,17 @@ dependencies = [ "universal-hash", ] +[[package]] +name = "portable-atomic" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280dc24453071f1b63954171985a0b0d30058d287960968b9b2aca264c8d4ee6" + [[package]] name = "postcard" -version = "1.0.10" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f7f0a8d620d71c457dd1d47df76bb18960378da56af4527aaa10f515eee732e" +checksum = "170a2601f67cc9dba8edd8c4870b15f71a6a2dc196daec8c83f72b59dff628a8" dependencies = [ "cobs", "embedded-io 0.4.0", @@ -2462,15 +2666,18 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99" dependencies = [ "unicode-ident", ] @@ -2484,41 +2691,52 @@ checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "pubky" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e41b59ac157d121a1e8c6ed46aafc6666b3ff7c5f41488b7923e1e33d2ca73e" +source = "git+https://github.com/pubky/pubky?branch=v0.4.0-rc1#30237c43cbd07d472cd5e5b77b64a343d832647e" dependencies = [ + "anyhow", "base64 0.22.1", "bytes", + "console_log", + "cookie", + "cookie_store", + "futures-lite", "js-sys", - "pkarr 2.2.1-alpha.2", - "pubky-common 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log", + "mainline", + "pkarr", + "pubky-common", "reqwest", - "thiserror 1.0.69", + "thiserror 2.0.11", "tokio", + "tracing", "url", "wasm-bindgen", "wasm-bindgen-futures", + "web-sys", ] [[package]] name = "pubky-app-specs" -version = "0.2.1" -source = "git+https://github.com/pubky/pubky-app-specs#270fcb2727d5c135e790d1776ccfb704e860fdd0" +version = "0.3.0" +source = "git+https://github.com/pubky/pubky-app-specs#f1c34f7624210e7249592e1553ce8b15f2730b59" dependencies = [ "base32", "blake3", + "js-sys", "mime", "serde", + "serde-wasm-bindgen", "serde_json", "url", "utoipa", + "wasm-bindgen", + "web-sys", ] [[package]] name = "pubky-common" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2176f9837b635d3fd4d85d36d5fc06baba85df53ca06f584af9686b85eb55177" +source = "git+https://github.com/pubky/pubky?branch=v0.4.0-rc1#30237c43cbd07d472cd5e5b77b64a343d832647e" dependencies = [ "argon2", "base32", @@ -2527,32 +2745,48 @@ dependencies = [ "ed25519-dalek", "js-sys", "once_cell", - "pkarr 2.2.1-alpha.2", + "pkarr", "postcard", "pubky-timestamp", "rand", "serde", - "thiserror 1.0.69", + "thiserror 2.0.11", ] [[package]] -name = "pubky-common" +name = "pubky-homeserver" version = "0.1.0" -source = "git+https://github.com/pubky/pubky-core.git?tag=pubky-v0.3.0#aede289c2606204fe944919b5024ee8cefe32c50" +source = "git+https://github.com/pubky/pubky?branch=v0.4.0-rc1#30237c43cbd07d472cd5e5b77b64a343d832647e" dependencies = [ - "argon2", + "anyhow", + "axum 0.7.9", + "axum-extra", + "axum-server", "base32", - "blake3", - "crypto_secretbox", - "ed25519-dalek", - "js-sys", - "once_cell", - "pkarr 2.2.1-alpha.2", + "bytes", + "clap", + "dirs-next", + "flume", + "futures-util", + "heed 0.21.0", + "hex", + "http-relay", + "httpdate", + "mainline", + "page_size", + "pkarr", + "pkarr-relay", "postcard", - "pubky-timestamp", - "rand", + "pubky-common", "serde", - "thiserror 1.0.69", + "tokio", + "toml", + "tower 0.5.2", + "tower-cookies", + "tower-http", + "tracing", + "tracing-subscriber", + "url", ] [[package]] @@ -2561,9 +2795,10 @@ version = "0.2.0" dependencies = [ "anyhow", "async-trait", - "axum 0.8.1", + "axum 0.8.2", "base32", "blake3", + "bytes", "chrono", "const_format", "criterion", @@ -2571,13 +2806,14 @@ dependencies = [ "env_logger", "httpc-test", "log", + "mainline", "neo4rs", "once_cell", - "pkarr 2.2.0", + "pkarr", "pubky", "pubky-app-specs", - "pubky-common 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pubky_homeserver", + "pubky-common", + "pubky-homeserver", "rand", "rand_distr", "redis", @@ -2587,7 +2823,7 @@ dependencies = [ "thiserror 2.0.11", "tokio", "tokio-shared-rt", - "tower-http 0.6.2", + "tower-http", "url", "utoipa", "utoipa-swagger-ui", @@ -2609,51 +2845,35 @@ dependencies = [ ] [[package]] -name = "pubky_homeserver" -version = "0.1.0" -source = "git+https://github.com/pubky/pubky-core.git?tag=pubky-v0.3.0#aede289c2606204fe944919b5024ee8cefe32c50" +name = "publicsuffix" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" dependencies = [ - "anyhow", - "axum 0.7.9", - "axum-extra", - "base32", - "bytes", - "clap", - "dirs-next", - "flume", - "futures-util", - "heed", - "hex", - "httpdate", - "libc", - "pkarr 2.2.1-alpha.2", - "postcard", - "pubky-common 0.1.0 (git+https://github.com/pubky/pubky-core.git?tag=pubky-v0.3.0)", - "serde", - "tokio", - "toml", - "tower-cookies", - "tower-http 0.5.2", - "tracing", - "tracing-subscriber", - "url", + "idna", + "psl-types", ] [[package]] -name = "publicsuffix" -version = "2.2.3" +name = "quanta" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96a8c1bda5ae1af7f99a2962e49df150414a43d62404644d98dd5c3a93d07457" +checksum = "3bd1fe6824cea6538803de3ff1bc0cf3949024db3d43c9643024bfb33a807c0e" dependencies = [ - "idna 0.3.0", - "psl-types", + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi", + "web-sys", + "winapi", ] [[package]] name = "quinn" -version = "0.11.2" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" dependencies = [ "bytes", "pin-project-lite", @@ -2661,46 +2881,51 @@ dependencies = [ "quinn-udp", "rustc-hash", "rustls", - "thiserror 1.0.69", + "socket2", + "thiserror 2.0.11", "tokio", "tracing", ] [[package]] name = "quinn-proto" -version = "0.11.3" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" dependencies = [ "bytes", + "getrandom", "rand", "ring", "rustc-hash", "rustls", + "rustls-pki-types", "slab", - "thiserror 1.0.69", + "thiserror 2.0.11", "tinyvec", "tracing", + "web-time", ] [[package]] name = "quinn-udp" -version = "0.5.2" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9096629c45860fc7fb143e125eb826b5e721e10be3263160c7d60ca832cf8c46" +checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" dependencies = [ + "cfg_aliases", "libc", "once_cell", "socket2", "tracing", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc" dependencies = [ "proc-macro2", ] @@ -2745,6 +2970,15 @@ dependencies = [ "rand", ] +[[package]] +name = "raw-cpuid" +version = "11.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6928fa44c097620b706542d428957635951bade7143269085389d42c8a4927e" +dependencies = [ + "bitflags", +] + [[package]] name = "rayon" version = "1.10.0" @@ -2767,16 +3001,14 @@ dependencies = [ [[package]] name = "redis" -version = "0.27.6" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09d8f99a4090c89cc489a94833c901ead69bfbf3877b4867d5482e321ee875bc" +checksum = "9f89727cba9cec05cc579942321ff6dd09fe57a8b3217f52f952301efa010da5" dependencies = [ "arc-swap", - "async-trait", "bytes", "combine", "futures-util", - "itertools 0.13.0", "itoa", "num-bigint", "percent-encoding", @@ -2793,9 +3025,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.2" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags", ] @@ -2813,14 +3045,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.5" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", ] [[package]] @@ -2834,13 +3066,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax 0.8.5", ] [[package]] @@ -2851,9 +3083,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" @@ -2936,7 +3168,7 @@ dependencies = [ "libc", "spin", "untrusted", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -2959,7 +3191,7 @@ dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.87", + "syn 2.0.96", "walkdir", ] @@ -2981,37 +3213,37 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[package]] name = "rustc-hash" -version = "1.1.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" +checksum = "c7fb8039b3032c191086b10f11f319a6e99e1e82889c5cc6046f515c9db1d497" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "8f287924602bf649d949c63dc8ac8b235fa5387d394020705b80c4eb597ce5b8" dependencies = [ "once_cell", "ring", @@ -3023,9 +3255,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" +checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -3036,25 +3268,27 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "2.1.2" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" dependencies = [ - "base64 0.22.1", "rustls-pki-types", ] [[package]] name = "rustls-pki-types" -version = "1.7.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +checksum = "d2bf47e6ff922db3825eb750c4e2ff784c6ff8fb9e13046ef6a1d1c5401b0b37" +dependencies = [ + "web-time", +] [[package]] name = "rustls-webpki" -version = "0.102.5" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a6fccd794a42c2c105b513a2f62bc3fd8f3ba57a4593677ceb0bd035164d78" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "ring", "rustls-pki-types", @@ -3063,9 +3297,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" [[package]] name = "ryu" @@ -3093,11 +3327,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -3121,9 +3355,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.11.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32" dependencies = [ "core-foundation-sys", "libc", @@ -3131,15 +3365,15 @@ dependencies = [ [[package]] name = "self_cell" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" +checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" [[package]] name = "semver" -version = "1.0.23" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "f79dfe2d285b0488816f30e700a7438c5a73d816b5b7d3ac72fbc48b0d185e03" [[package]] name = "serde" @@ -3150,6 +3384,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_bencode" version = "0.2.4" @@ -3177,14 +3422,14 @@ checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "serde_json" -version = "1.0.135" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9" +checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" dependencies = [ "itoa", "memchr", @@ -3204,9 +3449,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -3236,9 +3481,9 @@ dependencies = [ [[package]] name = "sha1_smol" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" [[package]] name = "sha2" @@ -3292,18 +3537,18 @@ checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] name = "simple-dns" -version = "0.6.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01607fe2e61894468c6dc0b26103abb073fb08b79a3d9e4b6d76a1a341549958" +checksum = "dee851d0e5e7af3721faea1843e8015e820a234f81fda3dea9247e15bac9a86a" dependencies = [ "bitflags", ] [[package]] name = "siphasher" -version = "0.3.11" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -3322,12 +3567,12 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -3339,6 +3584,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.7.3" @@ -3380,9 +3634,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.87" +version = "2.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" dependencies = [ "proc-macro2", "quote", @@ -3391,9 +3645,9 @@ dependencies = [ [[package]] name = "sync_wrapper" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" dependencies = [ "futures-core", ] @@ -3415,7 +3669,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -3441,14 +3695,16 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.10.1" +version = "3.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +checksum = "9a8a559c81686f576e8cd0290cd2a24a2a9ad80c98b3478856500fcbd7acd704" dependencies = [ "cfg-if", "fastrand", + "getrandom", + "once_cell", "rustix", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -3477,7 +3733,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -3488,7 +3744,7 @@ checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -3503,9 +3759,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" +checksum = "35e7868883861bd0e56d9ac6efcaaca0d6d5d82a2a7ec8209ff492c07cf37b21" dependencies = [ "deranged", "itoa", @@ -3524,9 +3780,9 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" +checksum = "2834e6017e3e5e4b9834939793b282bc03b37a3336245fa820e35e233e2a85de" dependencies = [ "num-conv", "time-core", @@ -3554,9 +3810,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +checksum = "022db8904dfa342efe721985167e9fcd16c29b226db4397ed752a761cfce81e8" dependencies = [ "tinyvec_macros", ] @@ -3582,7 +3838,7 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys", + "windows-sys 0.52.0", ] [[package]] @@ -3593,7 +3849,7 @@ checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -3608,12 +3864,11 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" +checksum = "5f6d0975eaace0cf0fcadee4e4aaa5da15b5c079146f2cffb67c113be122bf37" dependencies = [ "rustls", - "rustls-pki-types", "tokio", ] @@ -3636,14 +3891,14 @@ checksum = "1fe49a94e3a984b0d0ab97343dc3dcd52baae1ee13f005bfad39faea47d051dc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "tokio-util" -version = "0.7.11" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", @@ -3675,9 +3930,9 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.20" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -3698,6 +3953,7 @@ dependencies = [ "pin-project-lite", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -3733,23 +3989,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "tower-http" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" -dependencies = [ - "bitflags", - "bytes", - "http", - "http-body", - "http-body-util", - "pin-project-lite", - "tower-layer", - "tower-service", - "tracing", -] - [[package]] name = "tower-http" version = "0.6.2" @@ -3787,11 +4026,27 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +[[package]] +name = "tower_governor" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aea939ea6cfa7c4880f3e7422616624f97a567c16df67b53b11f0d03917a8e46" +dependencies = [ + "axum 0.7.9", + "forwarded-header-value", + "governor", + "http", + "pin-project", + "thiserror 1.0.69", + "tower 0.5.2", + "tracing", +] + [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "log", "pin-project-lite", @@ -3801,20 +4056,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" dependencies = [ "once_cell", "valuable", @@ -3833,9 +4088,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "e8189decb5ac0fa7bc8b96b7cb9b2701d60d48805aca84a238004d665fcc4008" dependencies = [ "matchers", "nu-ansi-term", @@ -3863,39 +4118,21 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" +checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.23" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-xid" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" [[package]] name = "universal-hash" @@ -3920,7 +4157,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", - "idna 1.0.3", + "idna", "percent-encoding", ] @@ -3960,7 +4197,7 @@ source = "git+https://github.com/juhaku/utoipa?rev=d522f744259dc4fde5f45d187983f dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] @@ -3968,7 +4205,7 @@ name = "utoipa-swagger-ui" version = "8.1.0" source = "git+https://github.com/juhaku/utoipa?rev=d522f744259dc4fde5f45d187983fb68c8167029#d522f744259dc4fde5f45d187983fb68c8167029" dependencies = [ - "axum 0.8.1", + "axum 0.8.2", "base64 0.22.1", "mime_guess", "regex", @@ -3982,9 +4219,9 @@ dependencies = [ [[package]] name = "valuable" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] name = "vcpkg" @@ -3994,9 +4231,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -4025,46 +4262,48 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" dependencies = [ "cfg-if", + "once_cell", + "rustversion", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "555d470ec0bc3bb57890405e5d4322cc9ea83cebb085523ced7be4144dac1e61" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4072,28 +4311,41 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" +dependencies = [ + "unicode-ident", +] [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -4101,9 +4353,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.26.3" +version = "0.26.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" +checksum = "5d642ff16b7e79272ae451b7322067cdc17cadf68c23264be9d94a32319efe7e" dependencies = [ "rustls-pki-types", ] @@ -4126,11 +4378,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -4187,6 +4439,15 @@ dependencies = [ "windows-targets", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -4253,9 +4514,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" -version = "0.6.18" +version = "0.6.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" dependencies = [ "memchr", ] @@ -4274,9 +4535,9 @@ checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" [[package]] name = "yoke" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" dependencies = [ "serde", "stable_deref_trait", @@ -4286,34 +4547,55 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "byteorder", + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.96", +] + [[package]] name = "zerofrom" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", "synstructure", ] @@ -4342,14 +4624,14 @@ checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.87", + "syn 2.0.96", ] [[package]] name = "zip" -version = "2.2.0" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc5e4288ea4057ae23afc69a4472434a87a2495cafce6632fd1c4ec9f5cf3494" +checksum = "ae9c1ea7b3a5e1f4b922ff856a129881167511563dc219869afe3787fc0c1a45" dependencies = [ "arbitrary", "crc32fast", @@ -4358,7 +4640,7 @@ dependencies = [ "flate2", "indexmap", "memchr", - "thiserror 1.0.69", + "thiserror 2.0.11", "zopfli", ] diff --git a/Cargo.toml b/Cargo.toml index 3b5fe9e2..b8700d12 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,19 +10,19 @@ default-run = "service" build = "build.rs" [dependencies] -pkarr = { git = "https://github.com/Pubky/pkarr", branch = "v3", package = "pkarr", features = [ - "async", -] } -pubky = "0.3.0" +bytes = "1.9.0" # Enforce this version as Pubky and Axum conflict v1.7.1 vs v1.9.0 +pkarr = { git = "https://github.com/pubky/pkarr", branch = "v3-rc1", package = "pkarr" } +mainline = { git = "https://github.com/pubky/mainline", branch = "v5-rc1", default-features = false } +pubky = { git = "https://github.com/pubky/pubky", branch = "v0.4.0-rc1" } pubky-app-specs = { git = "https://github.com/pubky/pubky-app-specs", features = [ "openapi", ] } tokio = { version = "1.43.0", features = ["full"] } axum = "0.8.1" -redis = { version = "0.27.6", features = ["tokio-comp", "json"] } +redis = { version = "0.28.1", features = ["tokio-comp", "json"] } neo4rs = "0.8.0" serde = { version = "1.0.217", features = ["derive"] } -serde_json = "1.0.135" +serde_json = "1.0.137" once_cell = "1.20.2" utoipa = { git = "https://github.com/juhaku/utoipa", rev = "d522f744259dc4fde5f45d187983fb68c8167029" } utoipa-swagger-ui = { git = "https://github.com/juhaku/utoipa", rev = "d522f744259dc4fde5f45d187983fb68c8167029", features = [ @@ -34,26 +34,23 @@ log = "0.4.22" env_logger = "0.11.6" const_format = "0.2.34" thiserror = "2.0.11" -chrono = "0.4.39" -pubky-common = "0.1.0" -reqwest = "0.12.12" +chrono = { version = "0.4.39", default-features = false, features = ["clock"] } +pubky-common = { git = "https://github.com/pubky/pubky", branch = "v0.4.0-rc1" } base32 = "0.5.1" blake3 = "1.5.5" url = "2.5.4" async-trait = "0.1.85" +reqwest = "0.12.9" [dev-dependencies] anyhow = "1.0.95" httpc-test = "0.1.10" criterion = { version = "0.5.1", features = ["async_tokio"] } -pubky_homeserver = { git = "https://github.com/pubky/pubky-core.git", tag = "pubky-v0.3.0" } +pubky-homeserver = { git = "https://github.com/pubky/pubky", branch = "v0.4.0-rc1" } rand = "0.8.5" rand_distr = "0.4.3" tokio-shared-rt = "0.1" -[patch.crates-io] -utoipa-swagger-ui = { git = "https://github.com/juhaku/utoipa", rev = "d522f744259dc4fde5f45d187983fb68c8167029" } - [lib] name = "pubky_nexus" path = "src/lib.rs" diff --git a/benches/tag.rs b/benches/tag.rs index 7aa379f0..ce6cba67 100644 --- a/benches/tag.rs +++ b/benches/tag.rs @@ -28,7 +28,7 @@ fn bench_get_user_tags(c: &mut Criterion) { &user_id, |b, &id| { b.to_async(&rt).iter(|| async { - let tag_details_list = TagUser::get_by_id(id, None, None, None, None, None) + let tag_details_list = TagUser::get_by_id(id, None, None, None, None, None, None) .await .unwrap(); criterion::black_box(tag_details_list); @@ -57,6 +57,7 @@ fn bench_get_wot_user_tags(c: &mut Criterion) { None, None, None, + None, Some("bbkdkhm97pytrb785rdpornkjpcxi331hpq446ckn6rhb4abiguy"), Some(3), ) @@ -144,7 +145,7 @@ fn bench_get_post_tags(c: &mut Criterion) { |b, ¶ms| { b.to_async(&rt).iter(|| async { let tag_details_list = - TagPost::get_by_id(params[0], Some(params[1]), None, None, None, None) + TagPost::get_by_id(params[0], Some(params[1]), None, None, None, None, None) .await .unwrap(); criterion::black_box(tag_details_list); diff --git a/benches/watcher.rs b/benches/watcher.rs index 657fbf81..3fc44d13 100644 --- a/benches/watcher.rs +++ b/benches/watcher.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use pkarr::mainline::Testnet; -use pubky::PubkyClient; +use mainline::Testnet; +use pubky::Client; use pubky_app_specs::{PubkyAppUser, PubkyAppUserLink}; use pubky_common::crypto::Keypair; use pubky_homeserver::Homeserver; @@ -11,17 +11,17 @@ use tokio::runtime::Runtime; mod setup; -/// Creates a homeserver and: -/// 1. Created a user +/// Create a homeserver and: +/// 1. Create a user /// 2. Sign up the user /// 3. Upload a profile.json /// 4. Delete the profile.json async fn create_homeserver_with_events() -> (Testnet, String) { // Create the test environment - let testnet = Testnet::new(3); + let testnet = Testnet::new(3).unwrap(); let homeserver = Homeserver::start_test(&testnet).await.unwrap(); - let client = PubkyClient::test(&testnet); - let homeserver_url = format!("http://localhost:{}", homeserver.port()); + let client = Client::builder().testnet(&testnet).build().unwrap(); + let homeserver_url = homeserver.url().to_string(); // Generate user data let keypair = Keypair::random(); @@ -48,10 +48,15 @@ async fn create_homeserver_with_events() -> (Testnet, String) { let url = format!("pubky://{}/pub/pubky.app/profile.json", user_id); // Create user profile - client.put(url.as_str(), &profile_json).await.unwrap(); + client + .put(url.as_str()) + .json(&profile_json) + .send() + .await + .unwrap(); // Delete the user profile - client.delete(url.as_str()).await.unwrap(); + client.delete(url.as_str()).send().await.unwrap(); (testnet, homeserver_url) } diff --git a/examples/new_homeserver_user.rs b/examples/new_homeserver_user.rs deleted file mode 100644 index 37977b8c..00000000 --- a/examples/new_homeserver_user.rs +++ /dev/null @@ -1,62 +0,0 @@ -use anyhow::Result; -use log::info; -use pkarr::mainline::Testnet; -use pubky::PubkyClient; -use pubky_app_specs::{traits::HasPath, PubkyAppUser, PubkyAppUserLink, PROTOCOL}; -use pubky_common::crypto::{Keypair, PublicKey}; -use pubky_nexus::{setup, Config}; - -#[tokio::main] -async fn main() -> Result<()> { - let config = Config::from_env(); - setup(&config).await; - - // Initialize the PubkyClient based on configuration - let client = match config.testnet { - true => { - let testnet = Testnet { - bootstrap: vec![config.bootstrap.clone()], - nodes: vec![], - }; - PubkyClient::builder().testnet(&testnet).build() - } - false => PubkyClient::default(), - }; - - // Generate a random keypair - let keypair = Keypair::random(); - let pk = keypair.public_key().to_z32(); - info!("The pubky id is: {}", pk); - - // Convert the homeserver from the config into a PublicKey - let homeserver = PublicKey::try_from(config.homeserver.as_str())?; - - // Perform signup - client.signup(&keypair, &homeserver).await?; - - // Create a new profile - let user = PubkyAppUser::new( - "Satoshi Nakamoto".to_string(), - Some("This is an example bio".to_string()), - Some("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAA1JREFUGFdjiO4O+w8ABL0CPPcYQa4AAAAASUVORK5CYII=".to_string()), - Some(vec![PubkyAppUserLink { - title: "My Website".to_string(), - url: "https://example.com".to_string(), - }]), - Some("Running Bitcoin".to_string()), - ); - - // Serialize the profile to JSON - let profile_json = serde_json::to_vec(&user)?; - - // Put some content into the Pubky homeserver - let url = format!( - "{protocol}{pk}{path}", - protocol = PROTOCOL, - pk = pk, - path = user.create_path() - ); - client.put(url.as_str(), &profile_json).await?; - - Ok(()) -} diff --git a/examples/stress_network_sim.rs b/examples/stress_network_sim.rs index f233a3f5..17c39c19 100644 --- a/examples/stress_network_sim.rs +++ b/examples/stress_network_sim.rs @@ -1,7 +1,6 @@ use anyhow::Result; use chrono::Utc; -use pkarr::mainline::Testnet; -use pubky::PubkyClient; +use pubky::Client; use pubky_app_specs::{ traits::{HashId, TimestampId}, PubkyAppFile, PubkyAppFollow, PubkyAppPost, PubkyAppPostKind, PubkyAppTag, PubkyAppUser, @@ -41,16 +40,10 @@ async fn main() -> Result<()> { let config = Config::from_env(); - // Initialize the PubkyClient based on configuration + // Initialize the Client based on configuration let client = match config.testnet { - true => { - let testnet = Testnet { - bootstrap: vec![config.bootstrap.clone()], - nodes: vec![], - }; - PubkyClient::builder().testnet(&testnet).build() - } - false => PubkyClient::default(), + true => Client::testnet()?, + false => Client::new()?, }; // Convert the homeserver from the config into a PublicKey @@ -217,7 +210,7 @@ async fn main() -> Result<()> { // Function to create a user async fn create_user( - client: &PubkyClient, + client: &Client, keypair: &Keypair, homeserver: &PublicKey, pk: &String, @@ -247,7 +240,12 @@ async fn create_user( }; let profile_url = format!("pubky://{}/pub/pubky.app/profile.json", pk); println!("PUT PROFILE: {}", pk); - if let Err(e) = client.put(profile_url.as_str(), &user_profile_json).await { + if let Err(e) = client + .put(profile_url.as_str()) + .json(&user_profile_json) + .send() + .await + { println!("ERROR: Failed to PUT profile for user {}: {}", pk, e); return false; } @@ -256,7 +254,7 @@ async fn create_user( // Function to create posts async fn create_posts( - client: &PubkyClient, + client: &Client, pk: &String, rng: &mut StdRng, posts_dist: &LogNormal, @@ -288,7 +286,7 @@ async fn create_posts( } }; println!("PUT POST: {}", post_id); - if let Err(e) = client.put(post_url.as_str(), &post_json).await { + if let Err(e) = client.put(post_url.as_str()).json(&post_json).send().await { println!( "ERROR: Failed to PUT post {} for user {}: {}", post_id, pk, e @@ -307,7 +305,7 @@ async fn create_posts( // Function to create follows async fn create_follows( - client: &PubkyClient, + client: &Client, pk: &String, current_index: usize, user_ids: &[String], @@ -350,7 +348,12 @@ async fn create_follows( } }; println!("PUT FOLLOW: {}", random_user); - if let Err(e) = client.put(follow_url.as_str(), &follow_json).await { + if let Err(e) = client + .put(follow_url.as_str()) + .json(&follow_json) + .send() + .await + { println!( "ERROR: Failed to PUT follow from user {} to {}: {}", pk, random_user, e @@ -369,7 +372,7 @@ async fn create_follows( // Function to create files async fn create_files( - client: &PubkyClient, + client: &Client, pk: &String, rng: &mut StdRng, files_dist: &LogNormal, @@ -395,7 +398,7 @@ async fn create_files( } }; println!("PUT BLOB: {}", blob_id); - if let Err(e) = client.put(blob_url.as_str(), &blob_json).await { + if let Err(e) = client.put(blob_url.as_str()).json(&blob_json).send().await { println!( "ERROR: Failed to PUT blob {} for user {}: {}", blob_id, pk, e @@ -425,7 +428,7 @@ async fn create_files( }; println!("PUT FILE: {}", file_id); - if let Err(e) = client.put(file_url.as_str(), &file_json).await { + if let Err(e) = client.put(file_url.as_str()).json(&file_json).send().await { println!( "ERROR: Failed to PUT file {} for user {}: {}", file_id, pk, e @@ -442,7 +445,7 @@ async fn create_files( // Function to create tags async fn create_tags( - client: &PubkyClient, + client: &Client, pk: &String, current_index: usize, user_ids: &[String], @@ -486,7 +489,7 @@ async fn create_tags( } }; println!("PUT USER TAG: {}", tag.create_id()); - if let Err(e) = client.put(tag_url.as_str(), &tag_json).await { + if let Err(e) = client.put(tag_url.as_str()).json(&tag_json).send().await { println!( "ERROR: Failed to PUT tag on user {} by user {}: {}", random_user, pk, e @@ -532,7 +535,7 @@ async fn create_tags( } }; println!("PUT POST TAG: {}", tag.create_id()); - if let Err(e) = client.put(tag_url.as_str(), &tag_json).await { + if let Err(e) = client.put(tag_url.as_str()).json(&tag_json).send().await { println!( "ERROR: Failed to PUT tag on post {} of user {} by user {}: {}", random_post_id, random_user, pk, e diff --git a/src/config.rs b/src/config.rs index e0f1ce29..17c638ae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,9 +16,7 @@ pub struct Config { pub server_port: String, pub reindex: bool, pub testnet: bool, - pub bootstrap: String, pub homeserver: String, - pub homeserver_url: String, pub events_limit: u32, pub watcher_sleep: u64, pub max_retries: u64, @@ -47,9 +45,7 @@ impl Config { .unwrap_or_else(|_| "false".to_string()) .parse() .unwrap_or(true), - bootstrap: env::var("BOOTSTRAP").unwrap_or_else(|_| "127.0.0.1:6881".to_string()), - homeserver: env::var("HOMESERVER").expect("HOMESERVER pubky not set"), - homeserver_url: env::var("HOMESERVER_URL").expect("HOMESERVER_URL not set"), + homeserver: env::var("HOMESERVER").expect("HOMESERVER pubky id not set"), events_limit: env::var("EVENTS_LIMIT") .unwrap_or("1000".to_string()) .parse() diff --git a/src/db/connectors/pubky.rs b/src/db/connectors/pubky.rs index 5edb9b17..690c91e3 100644 --- a/src/db/connectors/pubky.rs +++ b/src/db/connectors/pubky.rs @@ -1,21 +1,27 @@ use crate::Config; -use pkarr::mainline::Testnet; -use pubky::PubkyClient; +use mainline::Testnet; +use pubky::Client; use std::sync::Arc; -use std::time::Duration; use tokio::sync::OnceCell; static PUBKY_CONNECTOR_SINGLETON: OnceCell = OnceCell::const_new(); #[derive(Debug, Clone)] pub struct PubkyConnector { - pubky_client: Arc, + pubky_client: Arc, } #[derive(Debug)] pub enum PubkyConnectorError { AlreadyInitialized, NotInitialized, + IoError(std::io::Error), +} + +impl From for PubkyConnectorError { + fn from(e: std::io::Error) -> Self { + PubkyConnectorError::IoError(e) + } } impl std::fmt::Display for PubkyConnectorError { @@ -24,10 +30,8 @@ impl std::fmt::Display for PubkyConnectorError { PubkyConnectorError::AlreadyInitialized => { write!(f, "PubkyConnector has already been initialized") } - PubkyConnectorError::NotInitialized => write!( - f, - "PubkyConnector must be called before accessing PubkyClient connector" - ), + PubkyConnectorError::NotInitialized => write!(f, "PubkyConnector not initialized"), + PubkyConnectorError::IoError(e) => write!(f, "I/O error: {}", e), } } } @@ -45,32 +49,25 @@ impl PubkyConnector { return Ok(()); } let pubky_client = match testnet { - Some(testnet) => PubkyClient::builder() - .testnet(testnet) - .dht_request_timeout(Duration::from_millis(2000)) - .build(), + Some(testnet) => Client::builder().testnet(testnet).build()?, None => match config.testnet { - true => { - let testnet = Testnet { - bootstrap: vec![config.bootstrap.clone()], - nodes: vec![], - }; - PubkyClient::test(&testnet) - } - false => PubkyClient::default(), + true => Client::testnet()?, + false => Client::new()?, }, }; + let manager = Self { pubky_client: Arc::new(pubky_client), }; + PUBKY_CONNECTOR_SINGLETON .set(manager) .map_err(|_| PubkyConnectorError::AlreadyInitialized)?; Ok(()) } - /// Retrieves the shared PubkyClient connection. - pub fn get_pubky_client() -> Result, PubkyConnectorError> { + /// Retrieves the shared Client connection. + pub fn get_pubky_client() -> Result, PubkyConnectorError> { if let Some(resolver) = PUBKY_CONNECTOR_SINGLETON.get() { Ok(resolver.pubky_client.clone()) } else { diff --git a/src/db/kv/index/json.rs b/src/db/kv/index/json.rs index cff370cb..597d1e99 100644 --- a/src/db/kv/index/json.rs +++ b/src/db/kv/index/json.rs @@ -358,22 +358,24 @@ pub async fn get_multiple( let results: Vec> = if indexed_values.is_empty() { (0..keys.len()).map(|_| None).collect() } else { - deserialize_values(indexed_values) + deserialize_values(indexed_values)? }; Ok(results) } // Helper function to deserialize JSON strings to Vec> -fn deserialize_values(values: Vec>) -> Vec> { +fn deserialize_values( + values: Vec>, +) -> Result>, DynError> { values .into_iter() - .map(|opt| { - opt.and_then(|value_str| { - serde_json::from_str::>(&value_str) - .ok() - .and_then(|vec| vec.into_iter().next()) - }) + .map(|value_str| match value_str { + Some(value) => { + let value: Vec = serde_json::from_str(&value)?; + Ok(value.into_iter().next()) + } + None => Ok(None), }) .collect() } diff --git a/src/events/handlers/bookmark.rs b/src/events/handlers/bookmark.rs index 821961bf..7776ae4c 100644 --- a/src/events/handlers/bookmark.rs +++ b/src/events/handlers/bookmark.rs @@ -5,18 +5,17 @@ use crate::models::post::Bookmark; use crate::models::user::UserCounts; use crate::types::DynError; use crate::types::PubkyId; -use axum::body::Bytes; use chrono::Utc; use log::debug; use pubky_app_specs::traits::Validatable; use pubky_app_specs::PubkyAppBookmark; //TODO: only /posts/ are bookmarkable as of now. -pub async fn put(user_id: PubkyId, bookmark_id: String, blob: Bytes) -> Result<(), DynError> { +pub async fn put(user_id: PubkyId, bookmark_id: String, blob: &[u8]) -> Result<(), DynError> { debug!("Indexing new bookmark: {} -> {}", user_id, bookmark_id); // Deserialize and validate bookmark - let bookmark = ::try_from(&blob, &bookmark_id)?; + let bookmark = ::try_from(blob, &bookmark_id)?; sync_put(user_id, bookmark, bookmark_id).await } diff --git a/src/events/handlers/file.rs b/src/events/handlers/file.rs index 6488d02b..66582c4d 100644 --- a/src/events/handlers/file.rs +++ b/src/events/handlers/file.rs @@ -11,8 +11,7 @@ use crate::{ }, Config, }; -use axum::body::Bytes; -use log::debug; +use log::{debug, error}; use pubky_app_specs::{traits::Validatable, PubkyAppFile}; use tokio::{ fs::{self, remove_file, File}, @@ -23,12 +22,12 @@ pub async fn put( uri: String, user_id: PubkyId, file_id: String, - blob: Bytes, + blob: &[u8], ) -> Result<(), DynError> { debug!("Indexing new file resource at {}/{}", user_id, file_id); // Serialize and validate - let file_input = ::try_from(&blob, &file_id)?; + let file_input = ::try_from(blob, &file_id)?; debug!("file input {:?}", file_input); @@ -62,12 +61,17 @@ async fn ingest( ) -> Result { let pubky_client = PubkyConnector::get_pubky_client()?; - let blob = match pubky_client.get(pubkyapp_file.src.as_str()).await? { - Some(metadata) => metadata, + let response = match pubky_client.get(&pubkyapp_file.src).send().await { + Ok(response) => response, // TODO: Shape the error to avoid the retyManager - None => return Err("EVENT ERROR: no metadata in the file blob".into()), + Err(e) => { + error!("EVENT ERROR: could not retrieve file src blob"); + return Err(e.into()); + } }; + let blob = response.bytes().await?; + store_blob(file_id.to_string(), user_id.to_string(), &blob).await?; Ok(FileMeta { @@ -77,7 +81,7 @@ async fn ingest( }) } -async fn store_blob(name: String, path: String, blob: &Bytes) -> Result<(), DynError> { +async fn store_blob(name: String, path: String, blob: &[u8]) -> Result<(), DynError> { let storage_path = Config::from_env().file_path; // TODO: Is it well formatting. The file path already has / at the end let full_path = format!("{}/{}", storage_path, path); diff --git a/src/events/handlers/follow.rs b/src/events/handlers/follow.rs index 2ad88a2a..d146381f 100644 --- a/src/events/handlers/follow.rs +++ b/src/events/handlers/follow.rs @@ -5,10 +5,9 @@ use crate::models::notification::Notification; use crate::models::user::UserCounts; use crate::types::DynError; use crate::types::PubkyId; -use axum::body::Bytes; use log::debug; -pub async fn put(follower_id: PubkyId, followee_id: PubkyId, _blob: Bytes) -> Result<(), DynError> { +pub async fn put(follower_id: PubkyId, followee_id: PubkyId, _blob: &[u8]) -> Result<(), DynError> { debug!("Indexing new follow: {} -> {}", follower_id, followee_id); // TODO: in case we want to validate the content of this homeserver object or its `created_at` timestamp diff --git a/src/events/handlers/mute.rs b/src/events/handlers/mute.rs index cc33cb19..c070af4c 100644 --- a/src/events/handlers/mute.rs +++ b/src/events/handlers/mute.rs @@ -2,10 +2,9 @@ use crate::db::graph::exec::OperationOutcome; use crate::models::user::Muted; use crate::types::DynError; use crate::types::PubkyId; -use axum::body::Bytes; use log::debug; -pub async fn put(user_id: PubkyId, muted_id: PubkyId, _blob: Bytes) -> Result<(), DynError> { +pub async fn put(user_id: PubkyId, muted_id: PubkyId, _blob: &[u8]) -> Result<(), DynError> { debug!("Indexing new mute: {} -> {}", user_id, muted_id); // TODO: in case we want to validate the content of this homeserver object or its `created_at` timestamp diff --git a/src/events/handlers/post.rs b/src/events/handlers/post.rs index d4480639..dfac50b4 100644 --- a/src/events/handlers/post.rs +++ b/src/events/handlers/post.rs @@ -10,18 +10,17 @@ use crate::queries::get::post_is_safe_to_delete; use crate::types::DynError; use crate::types::PubkyId; use crate::{queries, RedisOps, ScoreAction}; -use axum::body::Bytes; use log::debug; use pubky_app_specs::{traits::Validatable, PubkyAppPost, PubkyAppPostKind}; use super::utils::post_relationships_is_reply; -pub async fn put(author_id: PubkyId, post_id: String, blob: Bytes) -> Result<(), DynError> { +pub async fn put(author_id: PubkyId, post_id: String, blob: &[u8]) -> Result<(), DynError> { // Process Post resource and update the databases debug!("Indexing new post: {}/{}", author_id, post_id); // Serialize and validate - let post = ::try_from(&blob, &post_id)?; + let post = ::try_from(blob, &post_id)?; sync_put(post, author_id, post_id).await } diff --git a/src/events/handlers/tag.rs b/src/events/handlers/tag.rs index e696dec5..802a93be 100644 --- a/src/events/handlers/tag.rs +++ b/src/events/handlers/tag.rs @@ -11,18 +11,17 @@ use crate::models::user::UserCounts; use crate::types::DynError; use crate::types::PubkyId; use crate::ScoreAction; -use axum::body::Bytes; use chrono::Utc; use log::debug; use pubky_app_specs::{traits::Validatable, PubkyAppTag}; use super::utils::post_relationships_is_reply; -pub async fn put(tagger_id: PubkyId, tag_id: String, blob: Bytes) -> Result<(), DynError> { +pub async fn put(tagger_id: PubkyId, tag_id: String, blob: &[u8]) -> Result<(), DynError> { debug!("Indexing new tag: {} -> {}", tagger_id, tag_id); // Deserialize and validate tag - let tag = ::try_from(&blob, &tag_id)?; + let tag = ::try_from(blob, &tag_id)?; // Parse the embeded URI to extract author_id and post_id using parse_tagged_post_uri let parsed_uri = ParsedUri::try_from(tag.uri.as_str())?; diff --git a/src/events/handlers/user.rs b/src/events/handlers/user.rs index d2ee1b79..71c6bef2 100644 --- a/src/events/handlers/user.rs +++ b/src/events/handlers/user.rs @@ -7,16 +7,15 @@ use crate::models::{ use crate::queries::get::user_is_safe_to_delete; use crate::types::DynError; use crate::types::PubkyId; -use axum::body::Bytes; use log::debug; use pubky_app_specs::{traits::Validatable, PubkyAppUser}; -pub async fn put(user_id: PubkyId, blob: Bytes) -> Result<(), DynError> { +pub async fn put(user_id: PubkyId, blob: &[u8]) -> Result<(), DynError> { // Process profile.json and update the databases debug!("Indexing new user profile: {}", user_id); // Serialize and validate - let user = ::try_from(&blob, &user_id)?; + let user = ::try_from(blob, &user_id)?; sync_put(user, user_id).await } diff --git a/src/events/mod.rs b/src/events/mod.rs index 46e37fac..a838dcdd 100644 --- a/src/events/mod.rs +++ b/src/events/mod.rs @@ -1,5 +1,6 @@ use crate::{db::connectors::pubky::PubkyConnector, types::PubkyId}; use log::{debug, error}; +use reqwest; use uri::ParsedUri; pub mod handlers; @@ -132,39 +133,37 @@ impl Event { // for every Resource Type let url = reqwest::Url::parse(&self.uri)?; let pubky_client = PubkyConnector::get_pubky_client()?; - let blob = match pubky_client.get(url).await { - Ok(Some(blob)) => blob, - Ok(None) => { - error!("WATCHER: No content found at {}", self.uri); - return Ok(()); - } + + let response = match pubky_client.get(url).send().await { + Ok(response) => response, Err(e) => { error!("WATCHER: Failed to fetch content at {}: {}", self.uri, e); return Err(e.into()); } }; + let blob = response.bytes().await?; match self.resource_type { - ResourceType::User { user_id } => handlers::user::put(user_id, blob).await?, + ResourceType::User { user_id } => handlers::user::put(user_id, &blob).await?, ResourceType::Post { author_id, post_id } => { - handlers::post::put(author_id, post_id, blob).await? + handlers::post::put(author_id, post_id, &blob).await? } ResourceType::Follow { follower_id, followee_id, - } => handlers::follow::put(follower_id, followee_id, blob).await?, + } => handlers::follow::put(follower_id, followee_id, &blob).await?, ResourceType::Mute { user_id, muted_id } => { - handlers::mute::put(user_id, muted_id, blob).await? + handlers::mute::put(user_id, muted_id, &blob).await? } ResourceType::Bookmark { user_id, bookmark_id, - } => handlers::bookmark::put(user_id, bookmark_id, blob).await?, + } => handlers::bookmark::put(user_id, bookmark_id, &blob).await?, ResourceType::Tag { user_id, tag_id } => { - handlers::tag::put(user_id, tag_id, blob).await? + handlers::tag::put(user_id, tag_id, &blob).await? } ResourceType::File { user_id, file_id } => { - handlers::file::put(self.uri, user_id, file_id, blob).await? + handlers::file::put(self.uri, user_id, file_id, &blob).await? } } diff --git a/src/events/processor.rs b/src/events/processor.rs index 2de553b3..a937fc27 100644 --- a/src/events/processor.rs +++ b/src/events/processor.rs @@ -3,12 +3,11 @@ use std::time::Duration; use super::Event; use crate::types::DynError; use crate::types::PubkyId; +use crate::PubkyConnector; use crate::{models::homeserver::Homeserver, Config}; use log::{debug, error, info}; -use reqwest::Client; pub struct EventProcessor { - http_client: Client, homeserver: Homeserver, limit: u32, max_retries: u64, @@ -26,7 +25,6 @@ impl EventProcessor { ); Ok(Self { - http_client: Client::new(), homeserver, limit, max_retries, @@ -40,11 +38,10 @@ impl EventProcessor { /// /// # Parameters /// - `homeserver_url`: The URL of the homeserver to be used in the test environment. - pub async fn test(homeserver_url: String) -> Self { - let id = PubkyId("test".to_string()); - let homeserver = Homeserver::new(id, homeserver_url).await.unwrap(); + pub async fn test(homeserver_id: String) -> Self { + let id = PubkyId(homeserver_id.to_string()); + let homeserver = Homeserver::new(id).await.unwrap(); Self { - http_client: Client::new(), homeserver, limit: 1000, max_retries: 3, @@ -61,18 +58,22 @@ impl EventProcessor { async fn poll_events(&mut self) -> Result>, Box> { debug!("Polling new events from homeserver"); - let res = self - .http_client - .get(format!( - "{}/events/?cursor={}&limit={}", - self.homeserver.url, self.homeserver.cursor, self.limit - )) - .send() - .await? - .text() - .await?; - let lines: Vec = res.trim().split('\n').map(|s| s.to_string()).collect(); + let response: String; + { + let pubky_client = PubkyConnector::get_pubky_client()?; + response = pubky_client + .get(format!( + "https://{}/events/?cursor={}&limit={}", + self.homeserver.id, self.homeserver.cursor, self.limit + )) + .send() + .await? + .text() + .await?; + } + + let lines: Vec = response.trim().split('\n').map(|s| s.to_string()).collect(); debug!("Homeserver response lines {:?}", lines); if lines.len() == 1 && lines[0].is_empty() { diff --git a/src/models/file/details.rs b/src/models/file/details.rs index 787fb459..dab210ab 100644 --- a/src/models/file/details.rs +++ b/src/models/file/details.rs @@ -16,26 +16,24 @@ pub struct FileUrls { } mod json_string { - use serde::{self, Deserialize, Deserializer, Serialize, Serializer}; + use serde::{self, Deserialize, Deserializer, Serializer}; - // Deserialize function: convert the JSON string into a struct - pub fn deserialize<'de, D, T>(deserializer: D) -> Result + pub fn serialize(value: &T, serializer: S) -> Result where - D: Deserializer<'de>, - T: Deserialize<'de>, + S: Serializer, + T: serde::Serialize, { - let json_str: &'de str = <&str>::deserialize(deserializer)?; - serde_json::from_str(json_str).map_err(serde::de::Error::custom) + let json_string = serde_json::to_string(value).map_err(serde::ser::Error::custom)?; + serializer.serialize_str(&json_string) } - // Serialize function: convert the struct back into a JSON string - pub fn serialize(value: &T, serializer: S) -> Result + pub fn deserialize<'de, D, T>(deserializer: D) -> Result where - S: Serializer, - T: Serialize, + D: Deserializer<'de>, + T: serde::de::DeserializeOwned, { - let json_str = serde_json::to_string(value).map_err(serde::ser::Error::custom)?; - serializer.serialize_str(&json_str) + let json_string = String::deserialize(deserializer)?; + serde_json::from_str(&json_string).map_err(serde::de::Error::custom) } } diff --git a/src/models/homeserver.rs b/src/models/homeserver.rs index 2c74b46d..74ad1be1 100644 --- a/src/models/homeserver.rs +++ b/src/models/homeserver.rs @@ -7,20 +7,15 @@ use serde::{Deserialize, Serialize}; #[derive(Serialize, Deserialize, Debug)] pub struct Homeserver { pub id: PubkyId, - pub url: String, // Ideally we should not need URL for `/events` streams pub cursor: String, } impl RedisOps for Homeserver {} impl Homeserver { - pub async fn new( - id: PubkyId, - url: String, - ) -> Result> { + pub async fn new(id: PubkyId) -> Result> { let hs = Homeserver { id, - url, cursor: "0000000000000".to_string(), }; // Store homeserver with initial cursor in Index @@ -44,24 +39,15 @@ impl Homeserver { pub async fn from_config(config: &Config) -> Result { let homeserver_id = config.homeserver.clone(); - let homeserver_url = config.homeserver_url.clone(); - // Create a PubkyId from the homeserver public key let id = PubkyId::try_from(&homeserver_id)?; // Attempt to load the homeserver cursor from Redis match Homeserver::get_from_index(&id).await? { - Some(mut hs) => { - // If the URL has changed in the config, update it - if hs.url != homeserver_url { - hs.url = homeserver_url; - hs.put_to_index().await?; - } - Ok(hs) - } + Some(hs) => Ok(hs), None => { // Create a new Homeserver instance with default cursor - Homeserver::new(id, homeserver_url).await + Homeserver::new(id).await } } } diff --git a/src/models/post/view.rs b/src/models/post/view.rs index 9c802f18..c2ade162 100644 --- a/src/models/post/view.rs +++ b/src/models/post/view.rs @@ -35,6 +35,7 @@ impl PostView { TagPost::get_by_id( author_id, Some(post_id), + None, limit_tags, limit_taggers, viewer_id, diff --git a/src/models/tag/traits/collection.rs b/src/models/tag/traits/collection.rs index d6af6c0c..d34b3e3e 100644 --- a/src/models/tag/traits/collection.rs +++ b/src/models/tag/traits/collection.rs @@ -33,6 +33,7 @@ where /// # Parameters /// - `user_id` - A string slice representing the ID of the user for whom the tags are being retrieved /// - `extra_param` - An optional string slice used as an additional filter or context in tag retrieval. If it is Some(), the value is post_id + /// - skip_tags - The number of tags to skip before retrieving results /// - `limit_tags` - An optional limit on the number of tags to retrieve. /// - `limit_taggers` - An optional limit on the number of taggers (users who have tagged) to retrieve. /// - `viewer_id` - An optional string slice representing the ID of the viewer or requester. @@ -47,6 +48,7 @@ where async fn get_by_id( user_id: &str, extra_param: Option<&str>, + skip_tags: Option, limit_tags: Option, limit_taggers: Option, viewer_id: Option<&str>, @@ -55,7 +57,16 @@ where // Query for the tags that are in its WoT // Actually we just apply that search to User node if viewer_id.is_some() && matches!(depth, Some(1..=3)) { - match Self::get_from_index(user_id, viewer_id, limit_tags, limit_taggers, true).await? { + match Self::get_from_index( + user_id, + viewer_id, + skip_tags, + limit_tags, + limit_taggers, + true, + ) + .await? + { Some(tag_details) => return Ok(Some(tag_details)), None => { let depth = depth.unwrap_or(1); @@ -69,8 +80,17 @@ where } } } - // Get global tags for that user - match Self::get_from_index(user_id, extra_param, limit_tags, limit_taggers, false).await? { + // Get global tags for that user/post + match Self::get_from_index( + user_id, + extra_param, + skip_tags, + limit_tags, + limit_taggers, + false, + ) + .await? + { Some(tag_details) => Ok(Some(tag_details)), None => { let graph_response = Self::get_from_graph(user_id, extra_param, None).await?; @@ -87,6 +107,7 @@ where /// # Arguments /// * user_id - The key of the user for whom to retrieve tags. /// * extra_param - An optional parameter for specifying additional constraints: post_id, viewer_id (for WoT search) + /// * skip_tags - The number of tags to skip before retrieving results /// * limit_tags - A limit on the number of tags to retrieve. /// * limit_taggers - A limit on the number of taggers to retrieve. /// * is_cache - A boolean indicating whether to retrieve tags from the cache or the primary index. @@ -97,11 +118,13 @@ where async fn get_from_index( user_id: &str, extra_param: Option<&str>, + skip_tags: Option, limit_tags: Option, limit_taggers: Option, is_cache: bool, ) -> Result>, DynError> { let limit_tags = limit_tags.unwrap_or(5); + let skip_tags = skip_tags.unwrap_or(0); let limit_taggers = limit_taggers.unwrap_or(5); let key_parts = Self::create_sorted_set_key_parts(user_id, extra_param, is_cache); // Prepare the extra prefix for cache search @@ -117,7 +140,7 @@ where &key_parts, None, None, - None, + Some(skip_tags), Some(limit_tags), SortOrder::Descending, cache_prefix.0, diff --git a/src/models/user/details.rs b/src/models/user/details.rs index 2d806ac3..540afff1 100644 --- a/src/models/user/details.rs +++ b/src/models/user/details.rs @@ -71,7 +71,10 @@ where .map_err(serde::de::Error::custom)?; Ok(Some(urls)) } - _ => Err(serde::de::Error::custom("Expected a string or an array")), + serde_json::Value::Null => Ok(None), + _ => Err(serde::de::Error::custom( + "Expected either a string, an array or null", + )), } } diff --git a/src/models/user/search.rs b/src/models/user/search.rs index 5c941e02..5030da23 100644 --- a/src/models/user/search.rs +++ b/src/models/user/search.rs @@ -1,6 +1,6 @@ use super::UserDetails; -use crate::types::DynError; use crate::RedisOps; +use crate::{models::traits::Collection, types::DynError}; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; @@ -57,6 +57,16 @@ impl UserSearch { /// /// This method takes a list of `UserDetails` and adds them all to the sorted set at once. pub async fn put_to_index(details_list: &[&UserDetails]) -> Result<(), DynError> { + // ensure existing records are deleted + Self::delete_existing_records( + details_list + .iter() + .map(|details| details.id.0.as_str()) + .collect::>() + .as_slice(), + ) + .await?; + // Collect all the `username:user_id` pairs and their corresponding scores let mut items: Vec<(f64, String)> = Vec::with_capacity(details_list.len()); @@ -87,4 +97,110 @@ impl UserSearch { ) .await } + + async fn delete_existing_records(user_ids: &[&str]) -> Result<(), DynError> { + if user_ids.is_empty() { + return Ok(()); + } + let mut records_to_delete: Vec = Vec::with_capacity(user_ids.len()); + let keys = user_ids + .iter() + .map(|&id| vec![id]) + .collect::>>(); + let users = UserDetails::get_from_index(keys.iter().map(|item| item.as_slice()).collect()) + .await? + .into_iter() + .flatten() + .collect::>(); + for user_id in user_ids { + let existing_username = users + .iter() + .find(|user| user.id.0 == *user_id) + .map(|user| user.name.to_lowercase()); + if let Some(existing_record) = existing_username { + let search_key = format!("{}:{}", existing_record, user_id); + records_to_delete.push(search_key); + } + } + + Self::remove_from_index_sorted_set( + &USER_NAME_KEY_PARTS, + records_to_delete + .iter() + .map(|item| item.as_str()) + .collect::>() + .as_slice(), + ) + .await?; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use chrono::Utc; + + use crate::{ + models::{ + traits::Collection, + user::{UserDetails, UserSearch}, + }, + setup, + types::{DynError, PubkyId}, + Config, RedisOps, + }; + + #[tokio_shared_rt::test(shared)] + async fn test_put_to_index_no_duplicates() -> Result<(), DynError> { + let config = Config::from_env(); + setup(&config).await; + // Test that the `put_to_index` method does not add duplicate records to the index + // when called with the same `UserDetails` multiple times. + + // Create a `UserDetails` object + let user_id = "user_id"; + let user_name = "Test User Duplicate"; + let user_details = UserDetails { + id: PubkyId(user_id.to_string()), + name: user_name.to_string(), + bio: None, + status: None, + links: None, + image: None, + indexed_at: Utc::now().timestamp_millis(), + }; + + user_details.put_to_graph().await?; + user_details + .put_index_json(vec![user_id].as_slice(), None) + .await?; + + // Call `put_to_index` with the same `UserDetails` object + UserSearch::put_to_index(&[&user_details]).await?; + + // Check that the index contains only one record for the user + let search_result = UserSearch::get_by_name(&user_name, None, None).await?; + assert_eq!(search_result.unwrap().0, vec![user_id.to_string()]); + + let new_user_name = "Some Other User Name"; + let new_user_details = UserDetails { + id: PubkyId(user_id.to_string()), + name: new_user_name.to_string(), + bio: None, + status: None, + links: None, + image: None, + indexed_at: Utc::now().timestamp_millis(), + }; + + // Call `put_to_index` with new user details + UserSearch::put_to_index(&[&new_user_details]).await?; + + // Check the previous record is deleted + // Check that the index contains only one record for the user + let search_result = UserSearch::get_by_name(&user_name, None, None).await?; + assert_eq!(search_result.is_none(), true); + + Ok(()) + } } diff --git a/src/models/user/view.rs b/src/models/user/view.rs index f4f121c2..68df891c 100644 --- a/src/models/user/view.rs +++ b/src/models/user/view.rs @@ -28,7 +28,7 @@ impl UserView { UserDetails::get_by_id(user_id), UserCounts::get_by_id(user_id), Relationship::get_by_id(user_id, viewer_id), - TagUser::get_by_id(user_id, None, None, None, viewer_id, depth) + TagUser::get_by_id(user_id, None, None, None, None, viewer_id, depth) )?; let details = match details { diff --git a/src/routes/v0/endpoints.rs b/src/routes/v0/endpoints.rs index 6b0eeda3..20382d7a 100644 --- a/src/routes/v0/endpoints.rs +++ b/src/routes/v0/endpoints.rs @@ -20,7 +20,7 @@ pub const USER_FRIENDS_ROUTE: &str = concatcp!(USER_ROUTE, "/friends"); pub const USER_MUTED_ROUTE: &str = concatcp!(USER_ROUTE, "/muted"); // -- POST endpoints -- -const POST_PREFIX: &str = concatcp!(VERSION_ROUTE, "/post"); +pub const POST_PREFIX: &str = concatcp!(VERSION_ROUTE, "/post"); pub const POST_ROUTE: &str = concatcp!(POST_PREFIX, "/{author_id}/{post_id}"); pub const POST_RELATIONSHIPS_ROUTE: &str = concatcp!(POST_ROUTE, "/relationships"); pub const POST_BOOKMARK_ROUTE: &str = concatcp!(POST_ROUTE, "/bookmark"); diff --git a/src/routes/v0/post/tags.rs b/src/routes/v0/post/tags.rs index 14fdadfa..4a57b00a 100644 --- a/src/routes/v0/post/tags.rs +++ b/src/routes/v0/post/tags.rs @@ -19,12 +19,13 @@ use utoipa::OpenApi; params( ("author_id" = String, Path, description = "Author Pubky ID"), ("post_id" = String, Path, description = "Post ID"), - ("limit_tags" = Option, Query, description = "Upper limit on the number of tags for the posts"), - ("limit_taggers" = Option, Query, description = "Upper limit on the number of taggers per tag"), + ("skip_tags" = Option, Query, description = "Skip N tags. Defaults to `0`"), + ("limit_tags" = Option, Query, description = "Upper limit on the number of tags for the posts. Defaults to `5`"), + ("limit_taggers" = Option, Query, description = "Upper limit on the number of taggers per tag. Defaults to `5`"), ), responses( - (status = 200, description = "Post tags", body = TagPost), (status = 404, description = "Post not found"), + (status = 200, description = "Post tags", body = Vec), (status = 500, description = "Internal server error") ) )] @@ -33,15 +34,16 @@ pub async fn post_tags_handler( Query(query): Query, ) -> Result>> { info!( - "GET {POST_TAGS_ROUTE} author_id:{}, post_id: {}, limit_tags:{:?}, limit_taggers:{:?}", - author_id, post_id, query.limit_tags, query.limit_taggers + "GET {POST_TAGS_ROUTE} author_id:{}, post_id: {}, skip_tags:{:?}, limit_tags:{:?}, limit_taggers:{:?}", + author_id, post_id, query.limit_tags, query.skip_tags, query.limit_taggers ); match TagPost::get_by_id( &author_id, Some(&post_id), + query.skip_tags, query.limit_tags, query.limit_taggers, - None, + None, // Avoid by default WoT tags in a Post None, // Avoid by default WoT tags in a Post ) .await @@ -61,11 +63,11 @@ pub async fn post_tags_handler( ("author_id" = String, Path, description = "Author Pubky ID"), ("label" = String, Path, description = "Tag name"), ("post_id" = String, Path, description = "Post ID"), - ("skip" = Option, Query, description = "Number of taggers to skip for pagination"), - ("limit" = Option, Query, description = "Number of taggers to return for pagination") + ("skip" = Option, Query, description = "Number of taggers to skip for pagination. Defaults to `0`"), + ("limit" = Option, Query, description = "Number of taggers to return for pagination. Defaults to `40`") ), responses( - (status = 200, description = "Post tags", body = TagPost), + (status = 200, description = "Post tags", body = Taggers), (status = 404, description = "Post not found"), (status = 500, description = "Internal server error") ) diff --git a/src/routes/v0/post/view.rs b/src/routes/v0/post/view.rs index 0d658dc5..3d410b28 100644 --- a/src/routes/v0/post/view.rs +++ b/src/routes/v0/post/view.rs @@ -18,8 +18,8 @@ use utoipa::OpenApi; ("author_id" = String, Path, description = "Author Pubky ID"), ("post_id" = String, Path, description = "Post Crockford32 ID"), ("viewer_id" = Option, Query, description = "Viewer Pubky ID"), - ("max_tags" = Option, Query, description = "Upper limit on the number of tags for the post"), - ("max_taggers" = Option, Query, description = "Upper limit on the number of taggers per tag") + ("limit_tags" = Option, Query, description = "Upper limit on the number of tags for the post"), + ("limit_taggers" = Option, Query, description = "Upper limit on the number of taggers per tag") ), responses( (status = 200, description = "Post", body = PostView), diff --git a/src/routes/v0/types.rs b/src/routes/v0/types.rs index ca3c2f96..9bb35d8d 100644 --- a/src/routes/v0/types.rs +++ b/src/routes/v0/types.rs @@ -5,6 +5,7 @@ use utoipa::ToSchema; #[derive(Default, Deserialize, Debug, ToSchema)] pub struct TagsQuery { pub limit_tags: Option, + pub skip_tags: Option, pub limit_taggers: Option, pub viewer_id: Option, #[serde(default, deserialize_with = "parse_string_to_u8")] diff --git a/src/routes/v0/user/tags.rs b/src/routes/v0/user/tags.rs index ed23abc1..5a3f8563 100644 --- a/src/routes/v0/user/tags.rs +++ b/src/routes/v0/user/tags.rs @@ -20,8 +20,9 @@ use utoipa::OpenApi; tag = "User", params( ("user_id" = String, Path, description = "User Pubky ID"), - ("limit_tags" = Option, Query, description = "Upper limit on the number of tags for the user"), - ("limit_taggers" = Option, Query, description = "Upper limit on the number of taggers per tag"), + ("skip_tags" = Option, Query, description = "Skip N tags. **Default** value 0"), + ("limit_tags" = Option, Query, description = "Upper limit on the number of tags for the user. **Default** value 5"), + ("limit_taggers" = Option, Query, description = "Upper limit on the number of taggers per tag. **Default** value 5"), ("viewer_id" = Option, Query, description = "Viewer Pubky ID"), ("depth" = Option, Query, description = "User trusted network depth, user following users distance. Numbers bigger than 4, will be ignored") ), @@ -36,13 +37,14 @@ pub async fn user_tags_handler( Query(query): Query, ) -> Result>> { info!( - "GET {USER_TAGS_ROUTE} user_id:{}, limit_tags:{:?}, limit_taggers:{:?}, viewer_id:{:?}, depth:{:?}", - user_id, query.limit_tags, query.limit_taggers, query.viewer_id, query.depth + "GET {USER_TAGS_ROUTE} user_id:{}, skip_tags:{:?}, limit_tags:{:?}, limit_taggers:{:?}, viewer_id:{:?}, depth:{:?}", + user_id, query.skip_tags, query.limit_tags, query.limit_taggers, query.viewer_id, query.depth ); match TagUser::get_by_id( &user_id, None, + query.skip_tags, query.limit_tags, query.limit_taggers, query.viewer_id.as_deref(), diff --git a/tests/service/all.rs b/tests/service/all.rs index 7b5fc7ab..12ec2c26 100644 --- a/tests/service/all.rs +++ b/tests/service/all.rs @@ -4,7 +4,6 @@ use std::{ }; use anyhow::Result; -use pubky_nexus::models::tag::TagDetails; use serde_json::json; const HOST_URL: &str = "http://localhost:8080"; @@ -104,53 +103,3 @@ async fn test_files_by_ids() -> Result<()> { Ok(()) } - -#[tokio::test] -async fn test_get_post() -> Result<()> { - let client = httpc_test::new_client(HOST_URL)?; - - let author_id = "y4euc58gnmxun9wo87gwmanu6kztt9pgw1zz1yp1azp7trrsjamy"; - let post_id = "2ZCW1TGR5BKG0"; - - let res = client - .do_get(&format!( - "/v0/post/{}/{}?viewer_id={}", - author_id, post_id, author_id - )) - .await?; - assert_eq!(res.status(), 200); - - let body = res.json_body()?; - - assert_eq!(body["details"]["content"], "I am told we can reply now!"); - assert_eq!(body["details"]["indexed_at"].as_u64(), Some(1718616844478)); - assert_eq!(body["details"]["id"], post_id); - assert_eq!(body["details"]["author"], author_id); - assert_eq!(body["details"]["attachments"].as_array().unwrap().len(), 1); - assert_eq!( - (body["details"]["attachments"].as_array().unwrap())[0], - "pubky://y4euc58gnmxun9wo87gwmanu6kztt9pgw1zz1yp1azp7trrsjamy/pub/pubky.app/files/2ZKH7K7M9G3G0".to_string() - ); - assert_eq!( - body["details"]["uri"], - "pubky://y4euc58gnmxun9wo87gwmanu6kztt9pgw1zz1yp1azp7trrsjamy/pub/pubky.app/posts/2ZCW1TGR5BKG0" - ); - assert_eq!(body["counts"]["tags"].as_u64(), Some(5)); - assert_eq!(body["counts"]["replies"].as_u64(), Some(2)); - assert_eq!(body["counts"]["reposts"].as_u64(), Some(1)); - assert_eq!(body["bookmark"]["indexed_at"].as_u64(), Some(1721764200000)); - assert_eq!(body["bookmark"]["id"], "2Z9PFGC3WWWW0"); - - // Panic if tags vector is bigger that 1 - let post_tag_object = body["tags"][0].clone(); - let post_tag: TagDetails = serde_json::from_value(post_tag_object.clone())?; - assert_eq!(post_tag.label, "pubky"); - - // Test non-existing post - let res = client - .do_get(&format!("/v0/post/{}/{}", author_id, "no_post")) - .await?; - assert_eq!(res.status(), 404); - - Ok(()) -} diff --git a/tests/service/mod.rs b/tests/service/mod.rs index 9647bd08..0b44904f 100644 --- a/tests/service/mod.rs +++ b/tests/service/mod.rs @@ -1,5 +1,6 @@ pub mod all; pub mod endpoints; +pub mod post; pub mod stream; pub mod tags; pub mod user; diff --git a/tests/service/post/mod.rs b/tests/service/post/mod.rs new file mode 100644 index 00000000..d5bb1106 --- /dev/null +++ b/tests/service/post/mod.rs @@ -0,0 +1,7 @@ +use pubky_nexus::routes::v0::endpoints; + +pub mod view; + +pub const ROOT_PATH: &str = endpoints::POST_PREFIX; +pub const CAIRO_USER: &str = "f5tcy5gtgzshipr6pag6cn9uski3s8tjare7wd3n7enmyokgjk1o"; +pub const ENCRYPTION_TAG: &str = "encryption"; diff --git a/tests/service/post/view.rs b/tests/service/post/view.rs new file mode 100644 index 00000000..41c065c2 --- /dev/null +++ b/tests/service/post/view.rs @@ -0,0 +1,144 @@ +use crate::service::{ + post::{CAIRO_USER, ENCRYPTION_TAG, ROOT_PATH}, + stream::post::{POST_H, TAG_LABEL_2}, + utils::{make_request, HOST_URL}, +}; +use anyhow::Result; +use pubky_nexus::models::tag::TagDetails; + +#[tokio::test] +async fn test_get_post_view() -> Result<()> { + let client = httpc_test::new_client(HOST_URL)?; + + let author_id = "y4euc58gnmxun9wo87gwmanu6kztt9pgw1zz1yp1azp7trrsjamy"; + let post_id = "2ZCW1TGR5BKG0"; + + let res = client + .do_get(&format!( + "/v0/post/{}/{}?viewer_id={}", + author_id, post_id, author_id + )) + .await?; + assert_eq!(res.status(), 200); + + let body = res.json_body()?; + + assert_eq!(body["details"]["content"], "I am told we can reply now!"); + assert_eq!(body["details"]["indexed_at"].as_u64(), Some(1718616844478)); + assert_eq!(body["details"]["id"], post_id); + assert_eq!(body["details"]["author"], author_id); + assert_eq!(body["details"]["attachments"].as_array().unwrap().len(), 1); + assert_eq!( + (body["details"]["attachments"].as_array().unwrap())[0], + "pubky://y4euc58gnmxun9wo87gwmanu6kztt9pgw1zz1yp1azp7trrsjamy/pub/pubky.app/files/2ZKH7K7M9G3G0".to_string() + ); + assert_eq!( + body["details"]["uri"], + "pubky://y4euc58gnmxun9wo87gwmanu6kztt9pgw1zz1yp1azp7trrsjamy/pub/pubky.app/posts/2ZCW1TGR5BKG0" + ); + assert_eq!(body["counts"]["tags"].as_u64(), Some(5)); + assert_eq!(body["counts"]["replies"].as_u64(), Some(2)); + assert_eq!(body["counts"]["reposts"].as_u64(), Some(1)); + assert_eq!(body["bookmark"]["indexed_at"].as_u64(), Some(1721764200000)); + assert_eq!(body["bookmark"]["id"], "2Z9PFGC3WWWW0"); + + // Panic if tags vector is bigger that 1 + let post_tag_object = body["tags"][0].clone(); + let post_tag: TagDetails = serde_json::from_value(post_tag_object.clone())?; + assert_eq!(post_tag.label, "pubky"); + + // Test non-existing post + let res = client + .do_get(&format!("/v0/post/{}/{}", author_id, "no_post")) + .await?; + assert_eq!(res.status(), 404); + + Ok(()) +} + +#[tokio::test] +async fn test_get_post_view_with_limit_tags() -> Result<()> { + let path = format!("{}/{}/{}?limit_tags=1", ROOT_PATH, CAIRO_USER, POST_H); + + let body = make_request(&path).await?; + //let post_tag: PostView = serde_json::from_value(body.clone())?; + assert!(body.is_object()); + + // Check the tag list + let tags = body["tags"] + .as_array() + .expect("Post tags should be an array"); + // Check the total posts using that tag + assert_eq!(tags.len(), 1); + + // opersource tag + assert_eq!(tags[0]["label"], TAG_LABEL_2); + assert_eq!(tags[0]["taggers_count"], 4); + let taggers = tags[0]["taggers"] + .as_array() + .expect("Tag taggers should be an array"); + assert_eq!(taggers.len(), 4); + + Ok(()) +} + +#[tokio::test] +async fn test_get_post_view_with_limit_taggers() -> Result<()> { + let path = format!("{}/{}/{}?limit_taggers=2", ROOT_PATH, CAIRO_USER, POST_H); + + let body = make_request(&path).await?; + + assert!(body.is_object()); + // Check the tag list + let tags = body["tags"] + .as_array() + .expect("Post tags should be an array"); + // Check the total posts using that tag + assert_eq!(tags.len(), 2); + + // opersource tag + assert_eq!(tags[0]["label"], TAG_LABEL_2); + assert_eq!(tags[0]["taggers_count"], 4); + let opensource_taggers = tags[0]["taggers"] + .as_array() + .expect("Tag taggers should be an array"); + assert_eq!(opensource_taggers.len(), 2); + + assert_eq!(tags[1]["label"], ENCRYPTION_TAG); + assert_eq!(tags[1]["taggers_count"], 2); + let encryption_taggers = tags[1]["taggers"] + .as_array() + .expect("Tag taggers should be an array"); + assert_eq!(encryption_taggers.len(), 2); + + Ok(()) +} + +#[tokio::test] +async fn test_get_post_view_with_limit_tags_and_taggers() -> Result<()> { + let path = format!( + "{}/{}/{}?limit_tags=1&limit_taggers=2", + ROOT_PATH, CAIRO_USER, POST_H + ); + + let body = make_request(&path).await?; + + assert!(body.is_object()); + + // Check the tag list + let tags = body["tags"] + .as_array() + .expect("Post tags should be an array"); + // Check the total posts using that tag + assert_eq!(tags.len(), 1); + + // opersource tag + assert_eq!(tags[0]["label"], TAG_LABEL_2); + assert_eq!(tags[0]["taggers_count"], 4); + let taggers = tags[0]["taggers"] + .as_array() + .expect("Tag taggers should be an array"); + assert_eq!(taggers.len(), 2); + + Ok(()) +} diff --git a/tests/service/tags/post.rs b/tests/service/tags/post.rs index b533fb5c..9f025623 100644 --- a/tests/service/tags/post.rs +++ b/tests/service/tags/post.rs @@ -9,7 +9,8 @@ const PEER_PUBKY: &str = "db6w58pd5h63fbhtd88y8zz7pai9rkjwqt9omg6i7dz31dynrgcy"; const POST_ID: &str = "HC3T5CEPBPHQ"; const FREE_LABEL: &str = "free"; -// TODO: Create deterministic integration tests +const BAHRINGER_USER: &str = "7kbjzgcx3xygokesys6jso13tt9u5n995p9q54a1co7cai9ujcso"; +const BAHRINGER_POST: &str = "2Z1N9M56X4EG0"; #[tokio::test] async fn test_post_tag() -> Result<()> { @@ -52,6 +53,61 @@ async fn test_user_tags_limit_tag_filter_active() -> Result<()> { Ok(()) } +#[tokio::test] +async fn test_user_tags_skip_tag_filter_active() -> Result<()> { + let path = format!( + "/v0/post/{}/{}/tags?skip_tags=7", + BAHRINGER_USER, BAHRINGER_POST + ); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 3); + + // Validate that the posts belong to the specified user's bookmarks + analyse_tag_details_structure(tags); + + // Analyse the tag that is in the 1st index + let hot_tag = TagMockup::new(String::from("emergent"), 1, 1); + compare_tag_details(&tags[0], hot_tag); + // Analyse the tag that is in the 3rd index + let hot_tag = TagMockup::new(String::from("cheap"), 1, 1); + compare_tag_details(&tags[2], hot_tag); + + Ok(()) +} + +#[tokio::test] +async fn test_user_tags_skip_and_limit_tag_filter_active() -> Result<()> { + let path = format!( + "/v0/post/{}/{}/tags?skip_tags=4&limit_tags=3", + BAHRINGER_USER, BAHRINGER_POST + ); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 3); + + // Validate that the posts belong to the specified user's bookmarks + analyse_tag_details_structure(tags); + + // Analyse the tag that is in the 1st index + let hot_tag = TagMockup::new(String::from("mutation"), 1, 1); + compare_tag_details(&tags[0], hot_tag); + // Analyse the tag that is in the 2nd index + let hot_tag = TagMockup::new(String::from("irritably"), 1, 1); + compare_tag_details(&tags[1], hot_tag); + // Analyse the tag that is in the 3rd index + let hot_tag = TagMockup::new(String::from("frantically"), 1, 1); + compare_tag_details(&tags[2], hot_tag); + + Ok(()) +} + #[tokio::test] async fn test_user_tags_limit_taggers_filter_active() -> Result<()> { let path = format!("/v0/post/{}/{}/tags?limit_taggers=1", PEER_PUBKY, POST_ID); diff --git a/tests/service/tags/user.rs b/tests/service/tags/user.rs index aeb85b52..97895e46 100644 --- a/tests/service/tags/user.rs +++ b/tests/service/tags/user.rs @@ -41,13 +41,87 @@ async fn test_user_tags_limit_tag_filter_active() -> Result<()> { // Validate that the posts belong to the specified user's bookmarks analyse_tag_details_structure(tags); - // // Analyse the tag that is in the 4th index + // // Analyse the tag that is in the 1st index let hot_tag = TagMockup::new(String::from("pubky"), 3, 3); compare_tag_details(&tags[0], hot_tag); Ok(()) } +const MEDHURST_USER: &str = "zdbg13k5gh4tfz9qz11quohrxetgqxs7awandu8h57147xddcuhy"; +const RECKLESSLY_TAG: &str = "recklessly"; +const EVEN_TAG: &str = "even"; +const WEBBED_TAG: &str = "webbed"; + +#[tokio::test] +async fn test_user_tags_skip_tag_filter_active() -> Result<()> { + let path = format!("/v0/user/{}/tags?skip_tags=1", MEDHURST_USER); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 5); + + // Validate that the posts belong to the specified user's bookmarks + analyse_tag_details_structure(tags); + + // // Analyse the tag that is in the 4th index + let tag = TagMockup::new(String::from(EVEN_TAG), 2, 2); + compare_tag_details(&tags[1], tag); + + let tag = TagMockup::new(String::from(RECKLESSLY_TAG), 1, 1); + compare_tag_details(&tags[4], tag); + + Ok(()) +} + +#[tokio::test] +async fn test_user_tags_skip_and_limit_tag_filter_active() -> Result<()> { + let path = format!("/v0/user/{}/tags?skip_tags=5&limit_tags=1", MEDHURST_USER); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 1); + + // Validate that the posts belong to the specified user's bookmarks + analyse_tag_details_structure(tags); + + // // Analyse the tag that is in the 4th index + let tag = TagMockup::new(String::from(RECKLESSLY_TAG), 1, 1); + compare_tag_details(&tags[0], tag); + + Ok(()) +} + +#[tokio::test] +async fn test_user_tags_skip_limit_and_taggers_limit_filter_active() -> Result<()> { + let path = format!( + "/v0/user/{}/tags?skip_tags=2&limit_tags=2&limit_taggers=1", + MEDHURST_USER + ); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 2); + + // Validate that the posts belong to the specified user's bookmarks + analyse_tag_details_structure(tags); + + // // Analyse the tag that is in the 4th index + let tag = TagMockup::new(String::from(EVEN_TAG), 1, 2); + compare_tag_details(&tags[0], tag); + + let tag = TagMockup::new(String::from(WEBBED_TAG), 1, 1); + compare_tag_details(&tags[1], tag); + + Ok(()) +} + #[tokio::test] async fn test_user_tags_limit_taggers_filter_active() -> Result<()> { let path = format!("/v0/user/{}/tags?limit_taggers=1", PUBKY_PEER); diff --git a/tests/service/tags/wot.rs b/tests/service/tags/wot.rs index 082ddbb5..1a4985ec 100644 --- a/tests/service/tags/wot.rs +++ b/tests/service/tags/wot.rs @@ -22,8 +22,8 @@ const USER_C: &str = "cuimec4ngawamq8wa6fjzki6boxmwqcm11x6g7ontufrjwgdaxqo"; #[tokio::test] async fn test_wot_user_tags_endpoints() -> Result<(), DynError> { let _ = clear_wot_tags_cache().await; - - // Make sure, we still not index the WoT tags + + // Make sure, we still not index the WoT tags requesting the taggers let path = format!( "/v0/user/{}/taggers/{}?viewer_id={}&depth=2", AURELIO_USER, ATHENS_TAG, EPICTTO_VIEWER @@ -43,7 +43,7 @@ async fn test_wot_user_tags_endpoints() -> Result<(), DynError> { let tags = body.as_array().expect("Tag list should be an array"); assert_eq!(tags.len(), 2); - // Validate that the posts belong to the specified user's bookmarks + // Validate that the posts tag structure analyse_tag_details_structure(tags); // Analyse the tag that is in the 4th index @@ -64,13 +64,51 @@ async fn test_wot_user_tags_endpoints() -> Result<(), DynError> { let tags = body.as_array().expect("Tag list should be an array"); assert_eq!(tags.len(), 1); - // Validate that the posts belong to the specified user's bookmarks + // Validate that the posts tag structure analyse_tag_details_structure(tags); // // Analyse the tag that is in the 4th index let athens_hot_tag = TagMockup::new(String::from(ATHENS_TAG), 3, 3); compare_tag_details(&tags[0], athens_hot_tag); + // => test_wot_user_tags_endpoint_with_tag_skip + let path = format!( + "/v0/user/{}/tags?viewer_id={}&depth=2&skip_tags=1", + AURELIO_USER, EPICTTO_VIEWER + ); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 1); + + // Validate that the posts tag structure + analyse_tag_details_structure(tags); + + // Analyse the tag that is in the 1st index + let now_hot_tag = TagMockup::new(String::from(NOW_TAG), 2, 2); + compare_tag_details(&tags[0], now_hot_tag); + + // => test_wot_user_tags_endpoint_with_tag_skip_and_taggers_limit + let path = format!( + "/v0/user/{}/tags?viewer_id={}&depth=2&skip_tags=1&limit_taggers=1", + AURELIO_USER, EPICTTO_VIEWER + ); + let body = make_request(&path).await?; + + assert!(body.is_array()); + + let tags = body.as_array().expect("Tag list should be an array"); + assert_eq!(tags.len(), 1); + + // Validate that the posts tag structure + analyse_tag_details_structure(tags); + + // Analyse the tag that is in the 1st index + let now_hot_tag = TagMockup::new(String::from(NOW_TAG), 1, 2); + compare_tag_details(&tags[0], now_hot_tag); + // => test_wot_user_tags_endpoint_with_tagger_limit let path = format!( "/v0/user/{}/tags?viewer_id={}&depth=2&limit_taggers=1", @@ -83,7 +121,7 @@ async fn test_wot_user_tags_endpoints() -> Result<(), DynError> { let tags = body.as_array().expect("Tag list should be an array"); assert_eq!(tags.len(), 2); - // Validate that the posts belong to the specified user's bookmarks + // Validate that the posts tag structure analyse_tag_details_structure(tags); // // Analyse the tag that is in the 4th index @@ -104,7 +142,7 @@ async fn test_wot_user_tags_endpoints() -> Result<(), DynError> { let tags = body.as_array().expect("Tag list should be an array"); assert_eq!(tags.len(), 1); - // Validate that the posts belong to the specified user's bookmarks + // Validate that the posts tag structure analyse_tag_details_structure(tags); // // Analyse the tag that is in the 4th index diff --git a/tests/watcher/bookmarks/del.rs b/tests/watcher/bookmarks/del.rs index d65d789d..406666bd 100644 --- a/tests/watcher/bookmarks/del.rs +++ b/tests/watcher/bookmarks/del.rs @@ -46,7 +46,6 @@ async fn test_homeserver_unbookmark() -> Result<()> { uri: format!("pubky://{}/pub/pubky.app/posts/{}", author_id, post_id), created_at: chrono::Utc::now().timestamp_millis(), }; - let bookmark_blob = serde_json::to_vec(&bookmark)?; let bookmark_id = bookmark.create_id(); let bookmark_url = format!( "pubky://{}/pub/pubky.app/bookmarks/{}", @@ -54,7 +53,7 @@ async fn test_homeserver_unbookmark() -> Result<()> { ); // Put bookmark - test.put(&bookmark_url, bookmark_blob).await.unwrap(); + test.put(&bookmark_url, bookmark).await.unwrap(); // Step 4: Delete bookmark test.del(&bookmark_url).await?; diff --git a/tests/watcher/bookmarks/raw.rs b/tests/watcher/bookmarks/raw.rs index 7d78b24e..09acec28 100644 --- a/tests/watcher/bookmarks/raw.rs +++ b/tests/watcher/bookmarks/raw.rs @@ -36,7 +36,6 @@ async fn test_homeserver_bookmark() -> Result<()> { uri: format!("pubky://{}/pub/pubky.app/posts/{}", user_id, post_id), created_at: chrono::Utc::now().timestamp_millis(), }; - let bookmark_blob = serde_json::to_vec(&bookmark)?; let bookmark_id = bookmark.create_id(); let bookmark_url = format!( "pubky://{}/pub/pubky.app/bookmarks/{}", @@ -44,7 +43,7 @@ async fn test_homeserver_bookmark() -> Result<()> { ); // Put bookmark - test.put(&bookmark_url, bookmark_blob).await.unwrap(); + test.put(&bookmark_url, bookmark).await.unwrap(); // Step 4: Verify the bookmark exists in Nexus // GRAPH_OP: Assert if the event writes the graph diff --git a/tests/watcher/bookmarks/viewer.rs b/tests/watcher/bookmarks/viewer.rs index edd6923f..257ba9d5 100644 --- a/tests/watcher/bookmarks/viewer.rs +++ b/tests/watcher/bookmarks/viewer.rs @@ -46,7 +46,6 @@ async fn test_homeserver_viewer_bookmark() -> Result<()> { uri: format!("pubky://{}/pub/pubky.app/posts/{}", user_id, post_id), created_at: chrono::Utc::now().timestamp_millis(), }; - let bookmark_blob = serde_json::to_vec(&bookmark)?; let bookmark_id = bookmark.create_id(); let bookmark_url = format!( "pubky://{}/pub/pubky.app/bookmarks/{}", @@ -54,7 +53,7 @@ async fn test_homeserver_viewer_bookmark() -> Result<()> { ); // Put bookmark - test.put(&bookmark_url, bookmark_blob).await.unwrap(); + test.put(&bookmark_url, bookmark).await.unwrap(); // Step 4: Verify the bookmark exists in Nexus // GRAPH_OP: Assert if the event writes the graph diff --git a/tests/watcher/files/create.rs b/tests/watcher/files/create.rs index 94634abb..e3a9cb4a 100644 --- a/tests/watcher/files/create.rs +++ b/tests/watcher/files/create.rs @@ -31,7 +31,11 @@ async fn test_put_pubkyapp_file() -> Result<()> { let blob_url = format!("pubky://{}/pub/pubky.app/blobs/{}", user_id, blob_id); let json_data = to_vec(blob)?; let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.put(blob_url.as_str(), &json_data).await?; + pubky_client + .put(blob_url.as_str()) + .json(&blob) + .send() + .await?; // Act let file = PubkyAppFile { diff --git a/tests/watcher/files/delete.rs b/tests/watcher/files/delete.rs index 44cc6e3a..2123db52 100644 --- a/tests/watcher/files/delete.rs +++ b/tests/watcher/files/delete.rs @@ -8,7 +8,6 @@ use pubky_nexus::{ models::{file::FileDetails, traits::Collection}, PubkyConnector, }; -use serde_json::to_vec; #[tokio_shared_rt::test(shared)] async fn test_delete_pubkyapp_file() -> Result<()> { @@ -29,9 +28,12 @@ async fn test_delete_pubkyapp_file() -> Result<()> { let blob = "Hello World!"; let blob_id = Timestamp::now().to_string(); let blob_url = format!("pubky://{}/pub/pubky.app/blobs/{}", user_id, blob_id); - let json_data = to_vec(blob)?; let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.put(blob_url.as_str(), &json_data).await?; + pubky_client + .put(blob_url.as_str()) + .json(&blob) + .send() + .await?; let file = PubkyAppFile { name: "myfile".to_string(), diff --git a/tests/watcher/network/counts.rs b/tests/watcher/network/counts.rs index 61baff98..180fc2a2 100644 --- a/tests/watcher/network/counts.rs +++ b/tests/watcher/network/counts.rs @@ -137,7 +137,9 @@ async fn test_large_network_scenario_counts() -> Result<()> { format!("pubky://{}/pub/pubky.app/mutes/{}", user_id, target_user_id); let pubky_client = PubkyConnector::get_pubky_client()?; pubky_client - .put(mute_url.as_str(), &serde_json::to_vec(&mute)?) + .put(mute_url.as_str()) + .json(&mute) + .send() .await?; _total_mutes += 1; } @@ -169,8 +171,7 @@ async fn test_large_network_scenario_counts() -> Result<()> { bookmark.create_id() ); - test.put(&bookmark_url, serde_json::to_vec(&bookmark)?) - .await?; + test.put(&bookmark_url, &bookmark).await?; total_bookmarks += 1; } } @@ -198,7 +199,7 @@ async fn test_large_network_scenario_counts() -> Result<()> { let tag_url = format!("pubky://{}/pub/pubky.app/tags/{}", user_id, tag.create_id()); - test.put(&tag_url, serde_json::to_vec(&tag)?).await?; + test.put(&tag_url, &tag).await?; total_tags += 1; // FAILS: possibly deletes a tag twice and decrements twice in index. @@ -263,7 +264,7 @@ async fn test_large_network_scenario_counts() -> Result<()> { let mute_uri = format!("pubky://{}/pub/pubky.app/mutes/{}", user_id, target_user_id); let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.delete(mute_uri.as_str()).await?; + pubky_client.delete(mute_uri.as_str()).send().await?; mute_set.remove(target_user_id); _total_unmutes += 1; } diff --git a/tests/watcher/posts/attachments.rs b/tests/watcher/posts/attachments.rs index d31290ee..b6e85e1c 100644 --- a/tests/watcher/posts/attachments.rs +++ b/tests/watcher/posts/attachments.rs @@ -28,7 +28,11 @@ async fn test_homeserver_post_attachments() -> Result<()> { let blob_url = format!("pubky://{}/pub/pubky.app/blobs/{}", user_id, blob_id); let json_data = to_vec(blob)?; let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.put(blob_url.as_str(), &json_data).await?; + pubky_client + .put(blob_url.as_str()) + .json(&blob) + .send() + .await?; test.ensure_event_processing_complete().await?; diff --git a/tests/watcher/posts/del_bookmarked_notification.rs b/tests/watcher/posts/del_bookmarked_notification.rs index d8e0f015..e6c4efda 100644 --- a/tests/watcher/posts/del_bookmarked_notification.rs +++ b/tests/watcher/posts/del_bookmarked_notification.rs @@ -50,13 +50,12 @@ async fn test_delete_bookmarked_post_notification() -> Result<()> { uri: format!("pubky://{}/pub/pubky.app/posts/{}", user_a_id, post_id), created_at: 0, }; - let bookmark_blob = serde_json::to_vec(&bookmark)?; let bookmark_url = format!( "pubky://{}/pub/pubky.app/bookmarks/{}", user_b_id, bookmark.create_id() ); - test.put(&bookmark_url, bookmark_blob).await?; + test.put(&bookmark_url, bookmark).await?; // User A deletes their post test.cleanup_post(&user_a_id, &post_id).await?; diff --git a/tests/watcher/posts/del_tagged_notification.rs b/tests/watcher/posts/del_tagged_notification.rs index fdc51f7f..b7f7e412 100644 --- a/tests/watcher/posts/del_tagged_notification.rs +++ b/tests/watcher/posts/del_tagged_notification.rs @@ -51,12 +51,11 @@ async fn test_delged_post_notification() -> Result<()> { label: label.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_id = tag.create_id(); let tag_url = format!("pubky://{}/pub/pubky.app/tags/{}", user_b_id, tag_id); // Put tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; // User A deletes their post test.cleanup_post(&user_a_id, &post_id).await?; diff --git a/tests/watcher/posts/del_with_relations.rs b/tests/watcher/posts/del_with_relations.rs index 339f955e..75ebe5a8 100644 --- a/tests/watcher/posts/del_with_relations.rs +++ b/tests/watcher/posts/del_with_relations.rs @@ -36,11 +36,10 @@ async fn test_delete_post_with_relationships() -> Result<()> { label: "funny".to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!("pubky://{}/pub/pubky.app/tags/{}", user_id, tag.create_id()); // Put tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; // Delete the post using the event handler test.cleanup_post(&user_id, &post_id).await?; diff --git a/tests/watcher/posts/edit_bookmarked_notification.rs b/tests/watcher/posts/edit_bookmarked_notification.rs index 07bc8a92..4cdc30e1 100644 --- a/tests/watcher/posts/edit_bookmarked_notification.rs +++ b/tests/watcher/posts/edit_bookmarked_notification.rs @@ -51,23 +51,23 @@ async fn test_edit_bookmarked_post_notification() -> Result<()> { uri: format!("pubky://{}/pub/pubky.app/posts/{}", user_a_id, post_id), created_at: 0, }; - let bookmark_blob = serde_json::to_vec(&bookmark)?; let bookmark_url = format!( "pubky://{}/pub/pubky.app/bookmarks/{}", user_b_id, bookmark.create_id() ); - test.put(&bookmark_url, bookmark_blob).await?; + test.put(&bookmark_url, bookmark).await?; // User A edits their post post.content = "Edited post by User A".to_string(); - let edited_post_blob = serde_json::to_vec(&post)?; let edited_url = format!("pubky://{}/pub/pubky.app/posts/{}", user_a_id, post_id); // Overwrite existing post in the homeserver for the edited one let pubky_client = PubkyConnector::get_pubky_client()?; pubky_client - .put(edited_url.as_str(), &edited_post_blob) + .put(edited_url.as_str()) + .json(&post) + .send() .await?; test.ensure_event_processing_complete().await?; diff --git a/tests/watcher/posts/edit_reply_parent_notification.rs b/tests/watcher/posts/edit_reply_parent_notification.rs index 14ca7c92..d919ba4f 100644 --- a/tests/watcher/posts/edit_reply_parent_notification.rs +++ b/tests/watcher/posts/edit_reply_parent_notification.rs @@ -59,13 +59,14 @@ async fn test_edit_parent_post_notification() -> Result<()> { // User A edits their original post post.content = "Edited post by User A".to_string(); - let edited_post_blob = serde_json::to_vec(&post)?; let edited_url = format!("pubky://{}/pub/pubky.app/posts/{}", user_a_id, post_id); // Overwrite existing post in the homeserver with the edited one let pubky_client = PubkyConnector::get_pubky_client()?; pubky_client - .put(edited_url.as_str(), &edited_post_blob) + .put(edited_url.as_str()) + .json(&post) + .send() .await?; test.ensure_event_processing_complete().await?; diff --git a/tests/watcher/posts/edit_reposted_notification.rs b/tests/watcher/posts/edit_reposted_notification.rs index 6d645646..c82569b3 100644 --- a/tests/watcher/posts/edit_reposted_notification.rs +++ b/tests/watcher/posts/edit_reposted_notification.rs @@ -59,13 +59,14 @@ async fn test_edit_reposted_post_notification() -> Result<()> { // User A edits their post post.content = "Edited post by User A".to_string(); - let edited_post_blob = serde_json::to_vec(&post)?; let edited_url = format!("pubky://{}/pub/pubky.app/posts/{}", user_a_id, post_id); // Overwrite existing post in the homeserver for the edited one let pubky_client = PubkyConnector::get_pubky_client()?; pubky_client - .put(edited_url.as_str(), &edited_post_blob) + .put(edited_url.as_str()) + .json(&post) + .send() .await?; test.ensure_event_processing_complete().await?; diff --git a/tests/watcher/posts/edit_tagged_notification.rs b/tests/watcher/posts/edit_tagged_notification.rs index a92b5d17..d6b7b9a4 100644 --- a/tests/watcher/posts/edit_tagged_notification.rs +++ b/tests/watcher/posts/edit_tagged_notification.rs @@ -52,22 +52,22 @@ async fn test_edit_tagged_post_notification() -> Result<()> { label: label.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_id = tag.create_id(); let tag_url = format!("pubky://{}/pub/pubky.app/tags/{}", user_b_id, tag_id); // Put tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; // User A edits their post post.content = "Edited post by User A".to_string(); - let edited_post_blob = serde_json::to_vec(&post)?; let edited_url = format!("pubky://{}/pub/pubky.app/posts/{}", user_a_id, post_id); // Overwrite existing post in the homeserver with the edited one let pubky_client = PubkyConnector::get_pubky_client()?; pubky_client - .put(edited_url.as_str(), &edited_post_blob) + .put(edited_url.as_str()) + .json(&post) + .send() .await?; test.ensure_event_processing_complete().await?; diff --git a/tests/watcher/posts/reply_engagement.rs b/tests/watcher/posts/reply_engagement.rs index a36525eb..af188a1c 100644 --- a/tests/watcher/posts/reply_engagement.rs +++ b/tests/watcher/posts/reply_engagement.rs @@ -139,7 +139,6 @@ async fn test_homeserver_reply_engagement_control() -> Result<()> { label: label.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", @@ -147,7 +146,7 @@ async fn test_homeserver_reply_engagement_control() -> Result<()> { tag.create_id() ); - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; // Check if reply post is not in total engagement index: Sorted:Posts:Global:TotalEngagement:user_id:post_id let total_engagement = check_member_total_engagement_user_posts(&[&author_id, &reply_id]) diff --git a/tests/watcher/tags/post_del.rs b/tests/watcher/tags/post_del.rs index 0e7cf2f7..bf75231f 100644 --- a/tests/watcher/tags/post_del.rs +++ b/tests/watcher/tags/post_del.rs @@ -56,7 +56,6 @@ async fn test_homeserver_del_tag_post() -> Result<()> { label: label.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_user_id, @@ -64,7 +63,7 @@ async fn test_homeserver_del_tag_post() -> Result<()> { ); // Step 3: Creat & Delete the tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; test.del(&tag_url).await?; @@ -84,6 +83,7 @@ async fn test_homeserver_del_tag_post() -> Result<()> { Some(&post_id), None, None, + None, false, ) .await diff --git a/tests/watcher/tags/post_muti_user.rs b/tests/watcher/tags/post_muti_user.rs index 2aba054b..5a457b11 100644 --- a/tests/watcher/tags/post_muti_user.rs +++ b/tests/watcher/tags/post_muti_user.rs @@ -72,14 +72,13 @@ async fn test_homeserver_multi_user() -> Result<()> { label: label_water.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_id, tag.create_id() ); // Put tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; tag_urls.push(tag_url) } @@ -91,14 +90,13 @@ async fn test_homeserver_multi_user() -> Result<()> { label: label_fire.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_id, tag.create_id() ); // Put tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; tag_urls.push(tag_url) } @@ -126,10 +124,16 @@ async fn test_homeserver_multi_user() -> Result<()> { assert!(post_fire_tag.taggers.contains(tagger_c_id)); // CACHE_OP: Check if the tag is correctly cached - let cache_post_tag = - ::get_from_index(author_id, Some(&post_id), None, None, false) - .await - .unwrap(); + let cache_post_tag = ::get_from_index( + author_id, + Some(&post_id), + None, + None, + None, + false, + ) + .await + .unwrap(); assert!(cache_post_tag.is_some()); let cache_tag_details = cache_post_tag.unwrap(); @@ -207,10 +211,16 @@ async fn test_homeserver_multi_user() -> Result<()> { // CACHE_OP: Check if the tag is correctly cached. // - Post:Taggers:author_id:post_id:label // - Sorted:Posts:Tag:author_id:post_id - let cache_post_tag = - ::get_from_index(author_id, Some(&post_id), None, None, false) - .await - .expect("Failed to get tag from cache"); + let cache_post_tag = ::get_from_index( + author_id, + Some(&post_id), + None, + None, + None, + false, + ) + .await + .expect("Failed to get tag from cache"); assert!( cache_post_tag.is_none(), "The SORTED SET index cannot exist for the tag" diff --git a/tests/watcher/tags/post_notification.rs b/tests/watcher/tags/post_notification.rs index 70d0d7e6..6c9ef8b1 100644 --- a/tests/watcher/tags/post_notification.rs +++ b/tests/watcher/tags/post_notification.rs @@ -57,7 +57,6 @@ async fn test_homeserver_tag_post_notification() -> Result<()> { created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_id, @@ -65,7 +64,7 @@ async fn test_homeserver_tag_post_notification() -> Result<()> { ); // Put tag - test.put(tag_url.as_str(), tag_blob).await?; + test.put(tag_url.as_str(), tag).await?; // GRAPH_OP let post_tag = find_post_tag(&author_id, &post_id, label) diff --git a/tests/watcher/tags/post_put.rs b/tests/watcher/tags/post_put.rs index 7e4700c0..33f1d1a1 100644 --- a/tests/watcher/tags/post_put.rs +++ b/tests/watcher/tags/post_put.rs @@ -47,7 +47,6 @@ async fn test_homeserver_put_tag_post() -> Result<()> { label: label.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_user_id, @@ -55,7 +54,7 @@ async fn test_homeserver_put_tag_post() -> Result<()> { ); // Put tag - test.put(&tag_url, tag_blob).await?; + test.put(&tag_url, tag).await?; // Step 4: Verify tag existence and data consistency @@ -71,7 +70,7 @@ async fn test_homeserver_put_tag_post() -> Result<()> { // CACHE_OP: Check if the tag is correctly cached let cache_post_tag = - TagPost::get_from_index(&tagger_user_id, Some(&post_id), None, None, false) + TagPost::get_from_index(&tagger_user_id, Some(&post_id), None, None, None, false) .await .unwrap(); diff --git a/tests/watcher/tags/user_notification.rs b/tests/watcher/tags/user_notification.rs index 2f973d2f..b6755f53 100644 --- a/tests/watcher/tags/user_notification.rs +++ b/tests/watcher/tags/user_notification.rs @@ -44,7 +44,6 @@ async fn test_homeserver_put_tag_user_notification() -> Result<()> { label: label.to_string(), created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_user_id, @@ -52,7 +51,7 @@ async fn test_homeserver_put_tag_user_notification() -> Result<()> { ); // Put tag - test.put(tag_url.as_str(), tag_blob).await?; + test.put(tag_url.as_str(), tag).await?; // Check if the tagged user received a notification let notifications = Notification::get_by_id(&tagged_user_id, Pagination::default()) diff --git a/tests/watcher/tags/user_to_self_put.rs b/tests/watcher/tags/user_to_self_put.rs index c60645e0..afc73903 100644 --- a/tests/watcher/tags/user_to_self_put.rs +++ b/tests/watcher/tags/user_to_self_put.rs @@ -32,11 +32,10 @@ async fn test_homeserver_put_tag_user_self() -> Result<()> { created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!("pubky://{}/pub/pubky.app/tags/{}", user_id, tag.create_id()); // Put tag - test.put(tag_url.as_str(), tag_blob).await?; + test.put(tag_url.as_str(), tag).await?; // Step 3: Verify tag existence and data consistency @@ -50,7 +49,7 @@ async fn test_homeserver_put_tag_user_self() -> Result<()> { assert_eq!(user_tag.taggers[0], user_id); // CACHE_OP: Check if the tag is correctly cached - let cache_user_tag = TagUser::get_from_index(&user_id, None, None, None, false) + let cache_user_tag = TagUser::get_from_index(&user_id, None, None, None, None, false) .await .expect("Failed to get tag from cache"); diff --git a/tests/watcher/tags/user_to_user_del.rs b/tests/watcher/tags/user_to_user_del.rs index c9d4e22c..ce39c4e2 100644 --- a/tests/watcher/tags/user_to_user_del.rs +++ b/tests/watcher/tags/user_to_user_del.rs @@ -45,7 +45,6 @@ async fn test_homeserver_del_tag_to_another_user() -> Result<()> { created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_user_id, @@ -53,7 +52,7 @@ async fn test_homeserver_del_tag_to_another_user() -> Result<()> { ); // Put tag - test.put(tag_url.as_str(), tag_blob).await?; + test.put(tag_url.as_str(), tag).await?; // Step 3: Delete the tag test.del(&tag_url).await?; @@ -64,7 +63,7 @@ async fn test_homeserver_del_tag_to_another_user() -> Result<()> { assert!(user_tag.is_none()); // CACHE_OP: Check if the tag is correctly updated in the cache - let cache_user_tag = TagUser::get_from_index(&tagged_user_id, None, None, None, false) + let cache_user_tag = TagUser::get_from_index(&tagged_user_id, None, None, None, None, false) .await .expect("Failed to get tag from cache"); diff --git a/tests/watcher/tags/user_to_user_put.rs b/tests/watcher/tags/user_to_user_put.rs index be6cd27d..b7931614 100644 --- a/tests/watcher/tags/user_to_user_put.rs +++ b/tests/watcher/tags/user_to_user_put.rs @@ -45,7 +45,6 @@ async fn test_homeserver_put_tag_user_another() -> Result<()> { created_at: Utc::now().timestamp_millis(), }; - let tag_blob = serde_json::to_vec(&tag)?; let tag_url = format!( "pubky://{}/pub/pubky.app/tags/{}", tagger_user_id, @@ -53,7 +52,7 @@ async fn test_homeserver_put_tag_user_another() -> Result<()> { ); // PUT post tag - test.put(tag_url.as_str(), tag_blob).await?; + test.put(tag_url.as_str(), tag).await?; // Step 3: Verify tag existence and data consistency @@ -67,7 +66,7 @@ async fn test_homeserver_put_tag_user_another() -> Result<()> { assert_eq!(user_tag.taggers[0], tagger_user_id); // CACHE_OP: Check if the tag is correctly cached - let cache_user_tag = TagUser::get_from_index(&tagged_user_id, None, None, None, false) + let cache_user_tag = TagUser::get_from_index(&tagged_user_id, None, None, None, None, false) .await .expect("Failed to get tag from cache"); diff --git a/tests/watcher/users/del_with_relations.rs b/tests/watcher/users/del_with_relations.rs index 54b45317..4bd71a71 100644 --- a/tests/watcher/users/del_with_relations.rs +++ b/tests/watcher/users/del_with_relations.rs @@ -125,7 +125,11 @@ async fn test_delete_user_with_relationships() -> Result<()> { let blob_url = format!("pubky://{}/pub/pubky.app/blobs/{}", user_with_id, blob_id); let json_data = to_vec(blob)?; let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.put(blob_url.as_str(), &json_data).await?; + pubky_client + .put(blob_url.as_str()) + .json(&blob) + .send() + .await?; // Act let file = PubkyAppFile { diff --git a/tests/watcher/utils/dht.rs b/tests/watcher/utils/dht.rs index 8f6b7e0c..7017aad9 100644 --- a/tests/watcher/utils/dht.rs +++ b/tests/watcher/utils/dht.rs @@ -1,5 +1,5 @@ use anyhow::{anyhow, Error}; -use pkarr::mainline::Testnet; +use mainline::Testnet; use std::sync::Arc; use tokio::sync::OnceCell; @@ -24,7 +24,7 @@ impl TestnetDHTNetwork { } let testnet = Self { // TODO: maybe add the node number in environment variable - nodes: Arc::new(Testnet::new(nodes)), + nodes: Arc::new(Testnet::new(nodes)?), }; DHT_TESTNET_NETWORK_SINGLETON .set(testnet) diff --git a/tests/watcher/utils/watcher.rs b/tests/watcher/utils/watcher.rs index d8e9bce1..5125d985 100644 --- a/tests/watcher/utils/watcher.rs +++ b/tests/watcher/utils/watcher.rs @@ -8,7 +8,6 @@ use pubky_app_specs::{ use pubky_common::crypto::Keypair; use pubky_homeserver::Homeserver; use pubky_nexus::{events::Event, setup, types::DynError, Config, EventProcessor, PubkyConnector}; -use serde_json::to_vec; /// Struct to hold the setup environment for tests pub struct WatcherTest { @@ -40,14 +39,14 @@ impl WatcherTest { let testnet = TestnetDHTNetwork::get_testnet_dht_nodes()?; let homeserver = Homeserver::start_test(&testnet).await?; - let homeserver_url = format!("http://localhost:{}", homeserver.port()); + let homeserver_id = homeserver.public_key().to_string(); match PubkyConnector::initialise(&config, Some(&testnet)) { Ok(_) => debug!("WatcherTest: PubkyConnector initialised"), Err(e) => debug!("WatcherTest: {}", e), } - let event_processor = EventProcessor::test(homeserver_url).await; + let event_processor = EventProcessor::test(homeserver_id).await; Ok(Self { config, @@ -70,19 +69,26 @@ impl WatcherTest { Ok(()) } - /// Sends a PUT request to the homeserver with the provided blob of data. + /// Sends a PUT request to the homeserver with the provided object of data. /// /// This function performs the following steps: /// 1. Retrieves the Pubky client from the PubkyConnector. - /// 2. Sends the blob data to the specified homeserver URI using a PUT request. + /// 2. Sends the object data to the specified homeserver URI using a PUT request. /// 3. Ensures that all event processing is complete after the PUT operation. /// /// # Parameters /// - `homeserver_uri`: The URI of the homeserver to write the data to. - /// - `blob`: A vector of bytes representing the data to be sent. - pub async fn put(&mut self, homeserver_uri: &str, blob: Vec) -> Result<()> { + /// - `object`: A generic type representing the data to be sent, which must implement `serde::Serialize`. + pub async fn put(&mut self, homeserver_uri: &str, object: T) -> Result<()> + where + T: serde::Serialize, + { let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.put(homeserver_uri, &blob).await?; + pubky_client + .put(homeserver_uri) + .json(&object) + .send() + .await?; self.ensure_event_processing_complete().await?; Ok(()) } @@ -99,7 +105,7 @@ impl WatcherTest { /// pub async fn del(&mut self, homeserver_uri: &str) -> Result<()> { let pubky_client = PubkyConnector::get_pubky_client()?; - pubky_client.delete(homeserver_uri).await?; + pubky_client.delete(homeserver_uri).send().await?; self.ensure_event_processing_complete().await?; Ok(()) } @@ -123,12 +129,10 @@ impl WatcherTest { pubky_client .signup(keypair, &self.homeserver.public_key()) .await?; - - let profile_json = to_vec(user)?; let url = format!("pubky://{}/pub/pubky.app/profile.json", user_id); // Write the user profile in the pubky.app repository - pubky_client.put(url.as_str(), &profile_json).await?; + pubky_client.put(url.as_str()).json(&user).send().await?; // Index to Nexus from Homeserver using the events processor self.ensure_event_processing_complete().await?; @@ -137,11 +141,12 @@ impl WatcherTest { pub async fn create_post(&mut self, user_id: &str, post: &PubkyAppPost) -> Result { let post_id = post.create_id(); - let post_json = to_vec(post)?; let url = format!("pubky://{}/pub/pubky.app/posts/{}", user_id, post_id); // Write the post in the pubky.app repository PubkyConnector::get_pubky_client()? - .put(url.as_str(), &post_json) + .put(url.as_str()) + .json(&post) + .send() .await?; // Index to Nexus from Homeserver using the events processor @@ -153,6 +158,7 @@ impl WatcherTest { let url = format!("pubky://{}/pub/pubky.app/profile.json", user_id); PubkyConnector::get_pubky_client()? .delete(url.as_str()) + .send() .await?; self.ensure_event_processing_complete().await?; Ok(()) @@ -162,6 +168,7 @@ impl WatcherTest { let url = format!("pubky://{}/pub/pubky.app/posts/{}", user_id, post_id); PubkyConnector::get_pubky_client()? .delete(url.as_str()) + .send() .await?; self.ensure_event_processing_complete().await?; Ok(()) @@ -173,10 +180,11 @@ impl WatcherTest { file: &PubkyAppFile, ) -> Result<(String, String)> { let file_id = file.create_id(); - let file_json = to_vec(file)?; let url = format!("pubky://{}/pub/pubky.app/files/{}", user_id, file_id); PubkyConnector::get_pubky_client()? - .put(url.as_str(), &file_json) + .put(url.as_str()) + .json(&file) + .send() .await?; self.ensure_event_processing_complete().await?; @@ -187,6 +195,7 @@ impl WatcherTest { let url = format!("pubky://{}/pub/pubky.app/files/{}", user_id, file_id); PubkyConnector::get_pubky_client()? .delete(url.as_str()) + .send() .await?; self.ensure_event_processing_complete().await?; Ok(()) @@ -196,13 +205,14 @@ impl WatcherTest { let follow_relationship = PubkyAppFollow { created_at: Utc::now().timestamp_millis(), }; - let blob = serde_json::to_vec(&follow_relationship)?; let follow_url = format!( "pubky://{}/pub/pubky.app/follows/{}", follower_id, followee_id ); PubkyConnector::get_pubky_client()? - .put(follow_url.as_str(), &blob) + .put(follow_url.as_str()) + .json(&follow_relationship) + .send() .await?; // Process the event self.ensure_event_processing_complete().await?; @@ -213,10 +223,11 @@ impl WatcherTest { let mute_relationship = PubkyAppFollow { created_at: Utc::now().timestamp_millis(), }; - let blob = serde_json::to_vec(&mute_relationship)?; let mute_url = format!("pubky://{}/pub/pubky.app/mutes/{}", muter_id, mutee_id); PubkyConnector::get_pubky_client()? - .put(mute_url.as_str(), &blob) + .put(mute_url.as_str()) + .json(&mute_relationship) + .send() .await?; // Process the event self.ensure_event_processing_complete().await?;