diff --git a/.cargo/config.toml b/.cargo/config.toml index 7acb319..1ce11dd 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,6 +1,6 @@ -[target.'cfg(target_os = "linux")'] -linker = "clang" -rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"] +#[target.'cfg(target_os = "linux")'] +#linker = "clang" +#rustflags = ["-C", "link-arg=-fuse-ld=/usr/bin/mold"] [target.x86_64-unknown-linux-gnu] rustflags = ["-Ctarget-cpu=native", "-C", "target-feature=+avx2,+avx,+sse2,+avx512f,+avx512bw,+avx512bf16,+avx512bitalg,+avx512bw,+avx512cd,+avx512dq,+avx512f,+avx512ifma,+avx512vbmi,+avx512vbmi2,+avx512vl,+avx512vnni,+avx512vpopcntdq,+avxifma,+avxneconvert,+avxvnni,+avxvnniint16,+avxvnniint8"] \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index e6fb26a..2495945 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,10 +7,6 @@ name = "Inflector" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] [[package]] name = "addr" @@ -21,15 +17,6 @@ dependencies = [ "psl-types", ] -[[package]] -name = "addr2line" -version = "0.24.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" -dependencies = [ - "gimli", -] - [[package]] name = "adler2" version = "2.0.1" @@ -43,7 +30,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" dependencies = [ "crypto-common", - "generic-array", + "generic-array 0.14.9", ] [[package]] @@ -54,7 +41,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ "cfg-if", "cipher", - "cpufeatures", + "cpufeatures 0.2.17", ] [[package]] @@ -73,14 +60,17 @@ dependencies = [ [[package]] name = "affinitypool" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dde2a385b82232b559baeec740c37809051c596f9b56e7da0d0da2c8e8f54f6" +checksum = "7a58b64a64aecad4ba7f2ccf0f79115f5d2d184b1e55307f78c20be07adc6633" dependencies = [ - "async-channel", + "crossbeam", + "libc", "num_cpus", - "thiserror 1.0.69", + "parking_lot", + "thiserror 2.0.18", "tokio", + "winapi", ] [[package]] @@ -89,7 +79,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "version_check", ] @@ -101,8 +91,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" dependencies = [ "cfg-if", - "const-random", - "getrandom 0.3.3", + "getrandom 0.3.4", "once_cell", "serde", "version_check", @@ -111,9 +100,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ "memchr", ] @@ -141,23 +130,17 @@ checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] name = "ammonia" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6b346764dd0814805de8abf899fe03065bcee69bb1a4771c785817e39f3978f" +checksum = "17e913097e1a2124b46746c980134e8c954bc17a6a59bb3fde96f088d126dde6" dependencies = [ - "cssparser", - "html5ever", + "cssparser 0.35.0", + "html5ever 0.35.0", "maplit", "tendril", "url", ] -[[package]] -name = "android-tzdata" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" - [[package]] name = "android_system_properties" version = "0.1.5" @@ -169,9 +152,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.20" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae563653d1938f79b1ab1b5e668c87c76a9930414574a6583a7b7e11a8e6192" +checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" dependencies = [ "anstyle", "anstyle-parse", @@ -184,62 +167,44 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" +checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" [[package]] name = "anstyle-parse" -version = "0.2.7" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e231f6134f61b71076a3eab506c379d4f36122f2af15a9ff04415ea4c3339e2" +checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "anstyle-wincon" -version = "3.0.10" +version = "3.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e0633414522a32ffaac8ac6cc8f748e090c5717661fddeea04219e2344f5f2a" +checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] -[[package]] -name = "any_ascii" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90c6333e01ba7235575b6ab53e5af10f1c327927fd97c36462917e289557ea64" - [[package]] name = "anyhow" -version = "1.0.99" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" -dependencies = [ - "backtrace", -] - -[[package]] -name = "approx" -version = "0.4.0" +version = "1.0.102" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f2a05fd1bd10b2527e20a2cd32d8873d115b8b39fe219ee25f42a8aca6ba278" -dependencies = [ - "num-traits", -] +checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c" [[package]] name = "approx" @@ -251,12 +216,12 @@ dependencies = [ ] [[package]] -name = "arbitrary" -version = "1.4.2" +name = "arc-swap" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +checksum = "6a3a1fd6f75306b68087b831f025c712524bcb19aad54e557b1129cfa0a2b207" dependencies = [ - "derive_arbitrary", + "rustversion", ] [[package]] @@ -267,7 +232,7 @@ checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072" dependencies = [ "base64ct", "blake2", - "cpufeatures", + "cpufeatures 0.2.17", "password-hash", ] @@ -290,58 +255,86 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "ascii-canvas" -version = "3.0.0" +name = "as-slice" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8824ecca2e851cec16968d54a01dd372ef8f95b244fb84b84e70128be347c3c6" +checksum = "45403b49e3954a4b8428a0ac21a4b7afadccf92bfd96273f1a58cd4812496ae0" dependencies = [ - "term", + "generic-array 0.12.4", + "generic-array 0.13.3", + "generic-array 0.14.9", + "stable_deref_trait", ] [[package]] -name = "async-channel" -version = "2.5.0" +name = "asn1-rs" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +checksum = "b7f43a50ac4fdca5df8e885c21b835997f0a1cdee65494a6847694a98652d9d8" dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", + "asn1-rs-derive", + "asn1-rs-impl", + "displaydoc", + "nom", + "num-traits", + "rusticata-macros", + "thiserror 2.0.18", + "time", +] + +[[package]] +name = "asn1-rs-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3109e49b1e4909e9db6515a30c633684d68cdeaa252f215214cb4fa1a5bfee2c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "synstructure", +] + +[[package]] +name = "asn1-rs-impl" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b18050c2cd6fe86c3a76584ef5e0baf286d038cda203eb6223df2cc413565f7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "async-executor" -version = "1.13.3" +name = "async-channel" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497c00e0fd83a72a79a39fcbd8e3e2f055d6f6c7e025f3b3d91f4f8e76527fb8" +checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" dependencies = [ - "async-task", "concurrent-queue", - "fastrand", - "futures-lite", + "event-listener-strategy", + "futures-core", "pin-project-lite", - "slab", ] [[package]] name = "async-graphql" -version = "7.0.17" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "036618f842229ba0b89652ffe425f96c7c16a49f7e3cb23b56fca7f61fd74980" +checksum = "1057a9f7ccf2404d94571dec3451ade1cb524790df6f1ada0d19c2a49f6b0f40" dependencies = [ "async-graphql-derive", "async-graphql-parser", "async-graphql-value", - "async-stream", + "async-io", "async-trait", + "asynk-strim", "base64 0.22.1", "bytes", "fnv", - "futures-timer", "futures-util", "http", - "indexmap 2.11.0", + "indexmap", "mime", "multer", "num-traits", @@ -351,31 +344,31 @@ dependencies = [ "serde_json", "serde_urlencoded", "static_assertions_next", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] name = "async-graphql-derive" -version = "7.0.17" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd45deb3dbe5da5cdb8d6a670a7736d735ba65b455328440f236dfb113727a3d" +checksum = "2e6cbeadc8515e66450fba0985ce722192e28443697799988265d86304d7cc68" dependencies = [ "Inflector", "async-graphql-parser", - "darling", + "darling 0.23.0", "proc-macro-crate", "proc-macro2", "quote", - "strum 0.26.3", - "syn 2.0.106", - "thiserror 1.0.69", + "strum 0.27.2", + "syn 2.0.117", + "thiserror 2.0.18", ] [[package]] name = "async-graphql-parser" -version = "7.0.17" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b7607e59424a35dadbc085b0d513aa54ec28160ee640cf79ec3b634eba66d3" +checksum = "e64ef70f77a1c689111e52076da1cd18f91834bcb847de0a9171f83624b07fbf" dependencies = [ "async-graphql-value", "pest", @@ -385,16 +378,34 @@ dependencies = [ [[package]] name = "async-graphql-value" -version = "7.0.17" +version = "7.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34ecdaff7c9cffa3614a9f9999bf9ee4c3078fe3ce4d6a6e161736b56febf2de" +checksum = "3e3ef112905abea9dea592fc868a6873b10ebd3f983e83308f995d6284e9ba41" dependencies = [ "bytes", - "indexmap 2.11.0", + "indexmap", "serde", "serde_json", ] +[[package]] +name = "async-io" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +dependencies = [ + "autocfg", + "cfg-if", + "concurrent-queue", + "futures-io", + "futures-lite", + "parking", + "polling", + "rustix", + "slab", + "windows-sys 0.61.2", +] + [[package]] name = "async-stream" version = "0.3.6" @@ -414,15 +425,9 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.89" @@ -431,18 +436,26 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] -name = "async_io_stream" -version = "0.3.3" +name = "asynk-strim" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6d7b9decdf35d8908a7e3ef02f64c5e9b1695e230154c0e8de3969142d9b94c" +checksum = "52697735bdaac441a29391a9e97102c74c6ef0f9b60a40cf109b1b404e29d2f6" dependencies = [ - "futures", - "pharos", - "rustc_version", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "atomic-polyfill" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cf2bce30dfe09ef0bfaef228b9d414faaf7e563035494d7fe092dba54b300f4" +dependencies = [ + "critical-section", ] [[package]] @@ -453,23 +466,74 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] -name = "backtrace" -version = "0.3.75" +name = "aws-lc-rs" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002" +checksum = "5ec2f1fc3ec205783a5da9a7e6c1509cc69dedf09a1949e412c1e18469326d00" dependencies = [ - "addr2line", - "cfg-if", - "libc", - "miniz_oxide", - "object", - "rustc-demangle", - "windows-targets 0.52.6", + "aws-lc-sys", + "untrusted 0.7.1", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.41.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a2f9779ce85b93ab6170dd940ad0169b5766ff848247aff13bb788b832fe3f4" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + +[[package]] +name = "axum" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" +dependencies = [ + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", ] [[package]] @@ -484,12 +548,6 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -498,9 +556,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "base64ct" -version = "1.8.0" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] name = "bbscope" @@ -514,24 +572,35 @@ dependencies = [ [[package]] name = "bcrypt" -version = "0.15.1" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e65938ed058ef47d92cf8b346cc76ef48984572ade631927e9937b5ffc7662c7" +checksum = "9a0f5948f30df5f43ac29d310b7476793be97c50787e6ef4a63d960a0d0be827" dependencies = [ "base64 0.22.1", "blowfish", - "getrandom 0.2.16", + "getrandom 0.3.4", "subtle", "zeroize", ] [[package]] name = "bincode" -version = "1.3.3" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +checksum = "36eaf5d7b090263e8150820482d5d93cd964a81e4019913c972f4edcc6edb740" dependencies = [ + "bincode_derive", "serde", + "unty", +] + +[[package]] +name = "bincode_derive" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf95709a440f45e986983918d0e8a1f30a9b1df04918fc828670606804ac3c09" +dependencies = [ + "virtue", ] [[package]] @@ -540,7 +609,7 @@ version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bitflags 2.9.4", + "bitflags", "cexpr", "clang-sys", "itertools 0.13.0", @@ -548,8 +617,8 @@ dependencies = [ "quote", "regex", "rustc-hash", - "shlex", - "syn 2.0.106", + "shlex 1.3.0", + "syn 2.0.117", ] [[package]] @@ -564,14 +633,14 @@ dependencies = [ "ecdsa", "ed25519-dalek", "elliptic-curve", - "getrandom 0.2.16", + "getrandom 0.2.17", "hex", "nom", "p256", "pkcs8 0.9.0", - "prost", - "prost-types", - "rand 0.8.5", + "prost 0.10.4", + "prost-types 0.10.1", + "rand 0.8.6", "rand_core 0.6.4", "regex", "serde_json", @@ -610,32 +679,35 @@ dependencies = [ [[package]] name = "bit-set" -version = "0.5.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ - "bit-vec", + "bit-vec 0.8.0", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" [[package]] -name = "bitflags" -version = "1.3.2" +name = "bit-vec" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +dependencies = [ + "serde", +] [[package]] name = "bitflags" -version = "2.9.4" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2261d10cca569e4643e526d8dc2e62e433cc8aba21ab764233731f8d369bf394" +checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -661,15 +733,16 @@ dependencies = [ [[package]] name = "blake3" -version = "1.8.2" +version = "1.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3888aaa89e4b2a40fca9848e400f6a658a5a3978de7be858e209cafa8be9a4a0" +checksum = "0aa83c34e62843d924f905e0f5c866eb1dd6545fc4d719e803d9ba6030371fce" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if", "constant_time_eq", + "cpufeatures 0.3.0", ] [[package]] @@ -678,7 +751,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" dependencies = [ - "generic-array", + "generic-array 0.14.9", ] [[package]] @@ -687,7 +760,7 @@ version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "generic-array", + "generic-array 0.14.9", ] [[package]] @@ -700,6 +773,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "bnum" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f781dba93de3a5ef6dc5b17c9958b208f6f3f021623b360fb605ea51ce443f10" + [[package]] name = "bon" version = "2.3.0" @@ -716,41 +795,48 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a2af3eac944c12cdf4423eab70d310da0a8e5851a18ffb192c0a5e3f7ae1663" dependencies = [ - "darling", + "darling 0.20.11", "ident_case", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "borsh" -version = "1.5.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce" +checksum = "cfd1e3f8955a5d7de9fab72fc8373fade9fb8a703968cb200ae3dc6cf08e185a" dependencies = [ "borsh-derive", + "bytes", "cfg_aliases", ] [[package]] name = "borsh-derive" -version = "1.5.7" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3" +checksum = "bfcfdc083699101d5a7965e49925975f2f55060f94f9a05e7187be95d530ca59" dependencies = [ "once_cell", "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] +[[package]] +name = "boxcar" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36f64beae40a84da1b4b26ff2761a5b895c12adc41dc25aaee1c4f2bbfe97a6e" + [[package]] name = "brotli" -version = "8.0.2" +version = "8.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" +checksum = "8119e4516436f5708bbc474a9d395bf12f1b5395e93a92a56e647ac3388c8610" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -759,9 +845,9 @@ dependencies = [ [[package]] name = "brotli-decompressor" -version = "5.0.0" +version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "874bb8112abecc98cbd6d81ea4fa7e94fb9449648c93cc89aa40c81c24d7de03" +checksum = "5962523e1b92ce1b5e793d9169b9943eece10d39f62550bc04bb605d75b94924" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", @@ -769,9 +855,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.19.0" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43" +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "bytecheck" @@ -797,9 +883,9 @@ dependencies = [ [[package]] name = "bytemuck" -version = "1.23.2" +version = "1.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3995eaeebcdf32f91f980d360f78732ddc061097ab4e39991ae7a6ace9194677" +checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec" dependencies = [ "bytemuck_derive", ] @@ -812,7 +898,7 @@ checksum = "f9abbd1bc6865053c427f7198e6af43bfdedc55ab791faed4fbd361d789575ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -829,9 +915,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" +checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" dependencies = [ "serde", ] @@ -848,41 +934,44 @@ dependencies = [ [[package]] name = "candle-core" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9f51e2ecf6efe9737af8f993433c839f956d2b6ed4fd2dd4a7c6d8b0fa667ff" +checksum = "c15b675b80d994b2eadb20a4bbe434eabeb454eac3ee5e2b4cf6f147ee9be091" dependencies = [ "byteorder", - "gemm 0.17.1", + "float8", + "gemm", "half", "intel-mkl-src", "libc", + "libm", "memmap2", "num-traits", "num_cpus", - "rand 0.9.2", + "rand 0.9.4", "rand_distr", "rayon", "safetensors", - "thiserror 1.0.69", - "ug", - "yoke 0.7.5", + "thiserror 2.0.18", + "yoke", "zip", ] [[package]] name = "candle-examples" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de8fb33ce13eecc55c30d56b3561c0af9d4d79e88190bac757089dc05bd1477f" +checksum = "fc143f693c0e21eb80419c8d76c56d6701bba8d754600f414e6e504371f31939" dependencies = [ "anyhow", "candle-core", "candle-nn", "candle-transformers", + "chrono", "csv", "hf-hub", "image", + "minijinja", "num-traits", "rayon", "safetensors", @@ -893,31 +982,32 @@ dependencies = [ [[package]] name = "candle-nn" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1980d53280c8f9e2c6cbe1785855d7ff8010208b46e21252b978badf13ad69d" +checksum = "3045fa9e7aef8567d209a27d56b692f60b96f4d0569f4c3011f8ca6715c65e03" dependencies = [ "candle-core", "half", + "libc", "num-traits", "rayon", "safetensors", "serde", - "thiserror 1.0.69", + "thiserror 2.0.18", ] [[package]] name = "candle-transformers" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "186cb80045dbe47e0b387ea6d3e906f02fb3056297080d9922984c90e90a72b0" +checksum = "b538ec4aa807c416a2ddd3621044888f188827862e2a6fcacba4738e89795d01" dependencies = [ "byteorder", "candle-core", "candle-nn", "fancy-regex", "num-traits", - "rand 0.9.2", + "rand 0.9.4", "rayon", "serde", "serde_json", @@ -936,71 +1026,14 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.36" +version = "1.2.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5252b3d2648e5eedbc1a6f501e3c795e07025c1e93bbf8bbdd6eef7f447a6d54" +checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f" dependencies = [ "find-msvc-tools", "jobserver", "libc", - "shlex", -] - -[[package]] -name = "cedar-policy" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d91e3b10a0f7f2911774d5e49713c4d25753466f9e11d1cd2ec627f8a2dc857" -dependencies = [ - "cedar-policy-core", - "cedar-policy-validator", - "itertools 0.10.5", - "lalrpop-util", - "ref-cast", - "serde", - "serde_json", - "smol_str", - "thiserror 1.0.69", -] - -[[package]] -name = "cedar-policy-core" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd2315591c6b7e18f8038f0a0529f254235fd902b6c217aabc04f2459b0d9995" -dependencies = [ - "either", - "ipnet", - "itertools 0.10.5", - "lalrpop", - "lalrpop-util", - "lazy_static", - "miette", - "regex", - "rustc_lexer", - "serde", - "serde_json", - "serde_with", - "smol_str", - "stacker", - "thiserror 1.0.69", -] - -[[package]] -name = "cedar-policy-validator" -version = "2.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e756e1b2a5da742ed97e65199ad6d0893e9aa4bd6b34be1de9e70bd1e6adc7df" -dependencies = [ - "cedar-policy-core", - "itertools 0.10.5", - "serde", - "serde_json", - "serde_with", - "smol_str", - "stacker", - "thiserror 1.0.69", - "unicode-security", + "shlex 2.0.1", ] [[package]] @@ -1014,9 +1047,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" [[package]] name = "cfg_aliases" @@ -1024,6 +1057,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.1", +] + [[package]] name = "chardetng" version = "0.1.17" @@ -1037,26 +1081,16 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.41" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "android-tzdata", "iana-time-zone", "js-sys", "num-traits", "serde", "wasm-bindgen", - "windows-link 0.1.3", -] - -[[package]] -name = "chrono-human-duration" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19283df3a144dfdeee6568e42ad7f0939d3c261bcdfe954b1a1098f6f7c1b908" -dependencies = [ - "chrono", + "windows-link 0.2.1", ] [[package]] @@ -1109,9 +1143,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.47" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eac00902d9d136acd712710d71823fb8ac8004ca445a89e73a41d45aa712931" +checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" dependencies = [ "clap_builder", "clap_derive", @@ -1119,9 +1153,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.47" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ad9bbf750e73b5884fb8a211a9424a1906c1e156724260fdae972f31d70e1d6" +checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" dependencies = [ "anstream", "anstyle", @@ -1131,21 +1165,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.47" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfd7eae0b0f1a6e63d4b13c9c478de77c2eb546fba158ad50b4203dc24b9f9c" +checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "clap_lex" -version = "0.7.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" +checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "classification" @@ -1167,66 +1201,35 @@ dependencies = [ ] [[package]] -name = "cli-table" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14da8d951cef7cc4f13ccc9b744d736963d57863c7e6fc33c070ea274546082c" -dependencies = [ - "cli-table-derive", - "csv", - "termcolor", - "unicode-width 0.2.1", -] - -[[package]] -name = "cli-table-derive" -version = "0.5.0" +name = "cmake" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c1b60bae2c3d45228dfb096046aa51ef6c300de70b658d7a13fcb0c4f832e" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "cc", ] [[package]] -name = "color-eyre" -version = "0.6.5" +name = "colorchoice" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5920befb47832a6d61ee3a3a846565cfa39b331331e68a3b1d1116630f2f26d" -dependencies = [ - "backtrace", - "color-spantrace", - "eyre", - "indenter", - "once_cell", - "owo-colors", - "tracing-error", -] +checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" [[package]] -name = "color-spantrace" -version = "0.3.0" +name = "combine" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b88ea9df13354b55bc7234ebcce36e6ef896aca2e42a15de9e10edce01b427" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "once_cell", - "owo-colors", - "tracing-core", - "tracing-error", + "bytes", + "memchr", ] -[[package]] -name = "colorchoice" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" - [[package]] name = "compact_str" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb1325a1cece981e8a296ab8f0f9b63ae357bd0784a9faaf548cc7b480707a" +checksum = "9dfdd1c2274d9aa354115b09dc9a901d6c5576818cdf70d14cae2bdb47df00ab" dependencies = [ "castaway", "cfg-if", @@ -1248,9 +1251,9 @@ dependencies = [ [[package]] name = "config" -version = "0.15.15" +version = "0.15.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0faa974509d38b33ff89282db9c3295707ccf031727c0de9772038ec526852ba" +checksum = "f316c6237b2d38be61949ecd15268a4c6ca32570079394a2444d9ce2c72a72d8" dependencies = [ "async-trait", "convert_case", @@ -1258,11 +1261,11 @@ dependencies = [ "pathdiff", "ron", "rust-ini", - "serde", "serde-untagged", + "serde_core", "serde_json", - "toml 0.9.5", - "winnow", + "toml 1.1.2+spec-1.1.0", + "winnow 1.0.3", "yaml-rust2", ] @@ -1275,10 +1278,22 @@ dependencies = [ "encode_unicode", "libc", "once_cell", - "unicode-width 0.2.1", + "unicode-width", "windows-sys 0.59.0", ] +[[package]] +name = "console" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" +dependencies = [ + "encode_unicode", + "libc", + "unicode-width", + "windows-sys 0.61.2", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -1300,16 +1315,16 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "once_cell", "tiny-keccak", ] [[package]] name = "constant_time_eq" -version = "0.3.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" +checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" [[package]] name = "content_inspector" @@ -1339,7 +1354,7 @@ dependencies = [ "base64 0.22.1", "hmac", "percent-encoding", - "rand 0.8.5", + "rand 0.8.6", "sha2 0.10.9", "subtle", "time", @@ -1372,6 +1387,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "counter" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "66e8e052be91f1c8aae2c1d81307d9f6e67f5f37001e3ddee419e971e73f03bc" +dependencies = [ + "num-traits", +] + [[package]] name = "cpufeatures" version = "0.2.17" @@ -1381,6 +1405,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -1390,6 +1423,34 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "critical-section" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" + +[[package]] +name = "crossbeam" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1137cd7e7fc0fb5d3c5a8678be38ec56e819125d8d7907411fe24ccb943faca8" +dependencies = [ + "crossbeam-channel", + "crossbeam-deque", + "crossbeam-epoch", + "crossbeam-queue", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-channel" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-deque" version = "0.8.6" @@ -1409,6 +1470,25 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-skiplist" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df29de440c58ca2cc6e587ec3d22347551a32435fbde9d2bff64e78a9ffa151b" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.21" @@ -1427,7 +1507,7 @@ version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" dependencies = [ - "generic-array", + "generic-array 0.14.9", "rand_core 0.6.4", "subtle", "zeroize", @@ -1439,7 +1519,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array", + "generic-array 0.14.9", "rand_core 0.6.4", "typenum", ] @@ -1453,7 +1533,20 @@ dependencies = [ "cssparser-macros", "dtoa-short", "itoa", - "phf", + "phf 0.11.3", + "smallvec", +] + +[[package]] +name = "cssparser" +version = "0.36.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dae61cf9c0abb83bd659dab65b7e4e38d8236824c85f0f804f173567bda257d2" +dependencies = [ + "cssparser-macros", + "dtoa-short", + "itoa", + "phf 0.13.1", "smallvec", ] @@ -1464,26 +1557,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "csv" -version = "1.3.1" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdc4883a9c96732e4733212c01447ebd805833b7275a73ca3ee080fd77afdaf" +checksum = "52cd9d68cf7efc6ddfaaee42e7288d3a99d613d4b50f76ce9827ae0c6e14f938" dependencies = [ "csv-core", "itoa", "ryu", - "serde", + "serde_core", ] [[package]] name = "csv-core" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d02f3b0da4c6504f86e9cd789d8dbafab48c2321be74e9987593de5a894d93d" +checksum = "704a3c26996a80471189265814dbc2c257598b96b8a7feae2d31ace646bb9782" dependencies = [ "memchr", ] @@ -1504,7 +1597,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest 0.10.7", "fiat-crypto", @@ -1521,7 +1614,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1530,8 +1623,18 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ - "darling_core", - "darling_macro", + "darling_core 0.20.11", + "darling_macro 0.20.11", +] + +[[package]] +name = "darling" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25ae13da2f202d56bd7f91c25fba009e7717a1e4a1cc98a76d844b65ae912e9d" +dependencies = [ + "darling_core 0.23.0", + "darling_macro 0.23.0", ] [[package]] @@ -1545,7 +1648,20 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.106", + "syn 2.0.117", +] + +[[package]] +name = "darling_core" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9865a50f7c335f53564bb694ef660825eb8610e0a53d3e11bf1b0d3df31e03b0" +dependencies = [ + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", ] [[package]] @@ -1554,38 +1670,36 @@ version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ - "darling_core", + "darling_core 0.20.11", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] -name = "dary_heap" -version = "0.3.8" +name = "darling_macro" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06d2e3287df1c007e74221c49ca10a95d557349e54b3a75dc2fb14712c751f04" +checksum = "ac3984ec7bd6cfa798e62b4a642426a5be0e68f9401cfc2a01e3fa9ea2fcdb8d" dependencies = [ - "serde", + "darling_core 0.23.0", + "quote", + "syn 2.0.117", ] [[package]] -name = "dashmap" -version = "5.5.3" +name = "dary_heap" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +checksum = "8b1e3a325bc115f096c8b77bbf027a7c2592230e70be2d985be950d3d5e60ebe" dependencies = [ - "cfg-if", - "hashbrown 0.14.5", - "lock_api", - "once_cell", - "parking_lot_core", + "serde", ] [[package]] name = "dashmap" -version = "6.1.0" +version = "6.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +checksum = "e6361d5c062261c78a176addb82d4c821ae42bed6089de0e12603cd25de2059c" dependencies = [ "cfg-if", "crossbeam-utils", @@ -1597,9 +1711,9 @@ dependencies = [ [[package]] name = "data-encoding" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2330da5de22e8a3cb63252ce2abb30116bf5265e89c0e01bc17015ce30a476" +checksum = "a4ae5f15dda3c708c0ade84bfee31ccab44a3da4f88015ed22f63732abe300c8" [[package]] name = "der" @@ -1622,24 +1736,27 @@ dependencies = [ ] [[package]] -name = "deranged" -version = "0.5.3" +name = "der-parser" +version = "10.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d630bccd429a5bb5a64b5e94f693bfc48c9f8566418fda4c494cc94f911f87cc" +checksum = "07da5016415d5a3c4dd39b11ed26f915f52fc4e0dc197d87908bc916e51bc1a6" dependencies = [ - "powerfmt", - "serde", + "asn1-rs", + "displaydoc", + "nom", + "num-bigint", + "num-traits", + "rusticata-macros", ] [[package]] -name = "derive_arbitrary" -version = "1.4.2" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "powerfmt", + "serde_core", ] [[package]] @@ -1657,10 +1774,10 @@ version = "0.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d5bcf7b024d6835cfb3d473887cd966994907effbe9227e8c8219824d06c4e8" dependencies = [ - "darling", + "darling 0.20.11", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1670,31 +1787,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab63b0e2bf4d5928aff72e83a7dace85d7bba5fe12dcc3c5a572d78caffd3f3c" dependencies = [ "derive_builder_core", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] -name = "deunicode" -version = "1.6.2" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] [[package]] -name = "diffy" -version = "0.4.2" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b545b8c50194bdd008283985ab0b31dba153cfd5b3066a92770634fbc0d7d291" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "nu-ansi-term", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", ] +[[package]] +name = "deunicode" +version = "1.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abd57806937c9cc163efc8ea3910e00a62e2aeb0b8119f1793a978088f8f6b04" + [[package]] name = "digest" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" dependencies = [ - "generic-array", + "generic-array 0.14.9", ] [[package]] @@ -1727,16 +1856,6 @@ dependencies = [ "dirs-sys 0.5.0", ] -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - [[package]] name = "dirs-sys" version = "0.4.1" @@ -1758,29 +1877,18 @@ dependencies = [ "libc", "option-ext", "redox_users 0.5.2", - "windows-sys 0.61.0", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users 0.4.6", - "winapi", + "windows-sys 0.61.2", ] [[package]] name = "displaydoc" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1802,17 +1910,11 @@ dependencies = [ "urlencoding", ] -[[package]] -name = "double-ended-peekable" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d05e1c0dbad51b52c38bda7adceef61b9efc2baf04acfe8726a8c4630a6f57" - [[package]] name = "dtoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6add3b8cff394282be81f3fc1a0605db594ed69890078ca6e2cab1c408bcf04" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] name = "dtoa-short" @@ -1824,20 +1926,10 @@ dependencies = [ ] [[package]] -name = "dyn-clone" -version = "1.0.20" +name = "dunce" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" - -[[package]] -name = "dyn-stack" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e53799688f5632f364f8fb387488dd05db9fe45db7011be066fc20e7027f8b" -dependencies = [ - "bytemuck", - "reborrow", -] +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "dyn-stack" @@ -1905,11 +1997,17 @@ dependencies = [ "zeroize", ] +[[package]] +name = "ego-tree" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2972feb8dffe7bc8c5463b1dacda1b0dfbed3710e50f977d965429692d74cd8" + [[package]] name = "either" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" +checksum = "91622ff5e7162018101f2fea40d6ebf4a78bbe5a49736a2020649edf9693679e" [[package]] name = "elliptic-curve" @@ -1921,7 +2019,7 @@ dependencies = [ "crypto-bigint", "digest 0.10.7", "ff", - "generic-array", + "generic-array 0.14.9", "group", "hkdf", "pem-rfc7468", @@ -1933,15 +2031,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "ena" -version = "0.14.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d248bdd43ce613d87415282f69b9bb99d947d290b10962dd6c56233312c2ad5" -dependencies = [ - "log", -] - [[package]] name = "encode_unicode" version = "1.0.0" @@ -1959,9 +2048,9 @@ dependencies = [ [[package]] name = "endian-type" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34f04666d835ff5d62e058c3995147c06f42fe86ff053337632bca83e42702d" +checksum = "869b0adbda23651a9c5c0c3d270aac9fcb52e8622a8f2b17e57802d7791962f2" [[package]] name = "enum-as-inner" @@ -1969,10 +2058,10 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1e6a265c649f3f5979b601d26f1d05ada116434c87741c9493cb56218f76cbc" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -1992,7 +2081,7 @@ checksum = "67c78a4d8fdf9953a5c9d458f9efe940fd97a0cab0941c075a813ac594733827" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -2003,22 +2092,23 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "erased-serde" -version = "0.4.6" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e004d887f51fcb9fef17317a2f3525c887d8aa3f4f50fed920816a688284a5b7" +checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" dependencies = [ "serde", + "serde_core", "typeid", ] [[package]] name = "errno" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -2075,31 +2165,35 @@ dependencies = [ ] [[package]] -name = "eyre" -version = "0.6.12" +name = "fancy-regex" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec" +checksum = "72cf461f865c862bb7dc573f643dd6a2b6842f7c30b07882b56bd148cc2761b8" dependencies = [ - "indenter", - "once_cell", + "bit-set", + "regex-automata", + "regex-syntax", ] [[package]] -name = "fancy-regex" -version = "0.13.0" +name = "fastnum" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "531e46835a22af56d1e3b66f04844bed63158bc094a628bec1d321d9b4c44bf2" +checksum = "4089ab2dfd45d8ddc92febb5ca80644389d5ebb954f40231274a3f18341762e2" dependencies = [ - "bit-set", - "regex-automata", - "regex-syntax", + "bnum", + "num-integer", + "num-traits", ] [[package]] name = "fastrand" -version = "2.3.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "9f1f227452a390804cdb637b74a86990f2a7d7ba4b7d5693aac9b4dd6defd8d6" +dependencies = [ + "getrandom 0.3.4", +] [[package]] name = "fdeflate" @@ -2128,38 +2222,53 @@ checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" [[package]] name = "filetime" -version = "0.2.26" +version = "0.2.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" dependencies = [ "cfg-if", "libc", - "libredox", - "windows-sys 0.60.2", ] [[package]] name = "find-msvc-tools" -version = "0.1.1" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd99930f64d146689264c637b5af2f0233a933bef0d8570e2526bf9e083192d" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" [[package]] -name = "fixedbitset" -version = "0.4.2" +name = "flatbuffers" +version = "25.12.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +checksum = "35f6839d7b3b98adde531effaf34f0c2badc6f4735d26fe74709d8e513a96ef3" +dependencies = [ + "bitflags", + "rustc_version", + "serde", +] [[package]] name = "flate2" -version = "1.1.5" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" dependencies = [ "crc32fast", "miniz_oxide", ] +[[package]] +name = "float8" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719a903cc23e4a89e87962c2a80fdb45cdaad0983a89bd150bb57b4c8571a7d5" +dependencies = [ + "half", + "num-traits", + "rand 0.9.4", + "rand_distr", +] + [[package]] name = "float_next_after" version = "1.0.0" @@ -2178,6 +2287,12 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "foreign-types" version = "0.3.2" @@ -2202,16 +2317,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "fraction" -version = "0.15.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f158e3ff0a1b334408dc9fb811cd99b446986f4d8b741bb08f9df1604085ae7" -dependencies = [ - "lazy_static", - "num", -] - [[package]] name = "fs_extra" version = "1.3.0" @@ -2242,9 +2347,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" dependencies = [ "futures-channel", "futures-core", @@ -2257,9 +2362,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" dependencies = [ "futures-core", "futures-sink", @@ -2267,15 +2372,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" [[package]] name = "futures-executor" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" dependencies = [ "futures-core", "futures-task", @@ -2284,9 +2389,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" [[package]] name = "futures-lite" @@ -2294,47 +2399,44 @@ version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" dependencies = [ - "fastrand", "futures-core", - "futures-io", - "parking", "pin-project-lite", ] [[package]] name = "futures-macro" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "futures-sink" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" [[package]] name = "futures-task" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" [[package]] name = "futures-timer" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "af43fadb8a98512d547e37b4e92e0ced13e205c061b87b4623eff01d918d6968" [[package]] name = "futures-util" -version = "0.3.31" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" dependencies = [ "futures-channel", "futures-core", @@ -2344,7 +2446,6 @@ dependencies = [ "futures-task", "memchr", "pin-project-lite", - "pin-utils", "slab", ] @@ -2359,246 +2460,146 @@ dependencies = [ [[package]] name = "gemm" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ab24cc62135b40090e31a76a9b2766a501979f3070fa27f689c27ec04377d32" -dependencies = [ - "dyn-stack 0.10.0", - "gemm-c32 0.17.1", - "gemm-c64 0.17.1", - "gemm-common 0.17.1", - "gemm-f16 0.17.1", - "gemm-f32 0.17.1", - "gemm-f64 0.17.1", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 10.7.0", - "seq-macro", -] - -[[package]] -name = "gemm" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab96b703d31950f1aeddded248bc95543c9efc7ac9c4a21fda8703a83ee35451" -dependencies = [ - "dyn-stack 0.13.2", - "gemm-c32 0.18.2", - "gemm-c64 0.18.2", - "gemm-common 0.18.2", - "gemm-f16 0.18.2", - "gemm-f32 0.18.2", - "gemm-f64 0.18.2", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 11.6.0", - "seq-macro", -] - -[[package]] -name = "gemm-c32" -version = "0.17.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9c030d0b983d1e34a546b86e08f600c11696fde16199f971cd46c12e67512c0" +checksum = "aa0673db364b12263d103b68337a68fbecc541d6f6b61ba72fe438654709eacb" dependencies = [ - "dyn-stack 0.10.0", - "gemm-common 0.17.1", + "dyn-stack", + "gemm-c32", + "gemm-c64", + "gemm-common", + "gemm-f16", + "gemm-f32", + "gemm-f64", "num-complex", "num-traits", "paste", - "raw-cpuid 10.7.0", + "raw-cpuid", "seq-macro", ] [[package]] name = "gemm-c32" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6db9fd9f40421d00eea9dd0770045a5603b8d684654816637732463f4073847" -dependencies = [ - "dyn-stack 0.13.2", - "gemm-common 0.18.2", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 11.6.0", - "seq-macro", -] - -[[package]] -name = "gemm-c64" -version = "0.17.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbb5f2e79fefb9693d18e1066a557b4546cd334b226beadc68b11a8f9431852a" +checksum = "086936dbdcb99e37aad81d320f98f670e53c1e55a98bee70573e83f95beb128c" dependencies = [ - "dyn-stack 0.10.0", - "gemm-common 0.17.1", + "dyn-stack", + "gemm-common", "num-complex", "num-traits", "paste", - "raw-cpuid 10.7.0", + "raw-cpuid", "seq-macro", ] [[package]] name = "gemm-c64" -version = "0.18.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfcad8a3d35a43758330b635d02edad980c1e143dc2f21e6fd25f9e4eada8edf" -dependencies = [ - "dyn-stack 0.13.2", - "gemm-common 0.18.2", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 11.6.0", - "seq-macro", -] - -[[package]] -name = "gemm-common" -version = "0.17.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2e7ea062c987abcd8db95db917b4ffb4ecdfd0668471d8dc54734fdff2354e8" +checksum = "20c8aeeeec425959bda4d9827664029ba1501a90a0d1e6228e48bef741db3a3f" dependencies = [ - "bytemuck", - "dyn-stack 0.10.0", - "half", + "dyn-stack", + "gemm-common", "num-complex", "num-traits", - "once_cell", "paste", - "pulp 0.18.22", - "raw-cpuid 10.7.0", - "rayon", + "raw-cpuid", "seq-macro", - "sysctl 0.5.5", ] [[package]] name = "gemm-common" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a352d4a69cbe938b9e2a9cb7a3a63b7e72f9349174a2752a558a8a563510d0f3" +checksum = "88027625910cc9b1085aaaa1c4bc46bb3a36aad323452b33c25b5e4e7c8e2a3e" dependencies = [ "bytemuck", - "dyn-stack 0.13.2", + "dyn-stack", "half", "libm", "num-complex", "num-traits", "once_cell", "paste", - "pulp 0.21.5", - "raw-cpuid 11.6.0", - "rayon", - "seq-macro", - "sysctl 0.6.0", -] - -[[package]] -name = "gemm-f16" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ca4c06b9b11952071d317604acb332e924e817bd891bec8dfb494168c7cedd4" -dependencies = [ - "dyn-stack 0.10.0", - "gemm-common 0.17.1", - "gemm-f32 0.17.1", - "half", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 10.7.0", + "pulp", + "raw-cpuid", "rayon", "seq-macro", + "sysctl", ] [[package]] name = "gemm-f16" -version = "0.18.2" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff95ae3259432f3c3410eaa919033cd03791d81cebd18018393dc147952e109" +checksum = "e3df7a55202e6cd6739d82ae3399c8e0c7e1402859b30e4cb780e61525d9486e" dependencies = [ - "dyn-stack 0.13.2", - "gemm-common 0.18.2", - "gemm-f32 0.18.2", + "dyn-stack", + "gemm-common", + "gemm-f32", "half", "num-complex", "num-traits", "paste", - "raw-cpuid 11.6.0", + "raw-cpuid", "rayon", "seq-macro", ] [[package]] name = "gemm-f32" -version = "0.17.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9a69f51aaefbd9cf12d18faf273d3e982d9d711f60775645ed5c8047b4ae113" +checksum = "02e0b8c9da1fbec6e3e3ab2ce6bc259ef18eb5f6f0d3e4edf54b75f9fd41a81c" dependencies = [ - "dyn-stack 0.10.0", - "gemm-common 0.17.1", + "dyn-stack", + "gemm-common", "num-complex", "num-traits", "paste", - "raw-cpuid 10.7.0", + "raw-cpuid", "seq-macro", ] [[package]] -name = "gemm-f32" -version = "0.18.2" +name = "gemm-f64" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc8d3d4385393304f407392f754cd2dc4b315d05063f62cf09f47b58de276864" +checksum = "056131e8f2a521bfab322f804ccd652520c79700d81209e9d9275bbdecaadc6a" dependencies = [ - "dyn-stack 0.13.2", - "gemm-common 0.18.2", + "dyn-stack", + "gemm-common", "num-complex", "num-traits", "paste", - "raw-cpuid 11.6.0", + "raw-cpuid", "seq-macro", ] [[package]] -name = "gemm-f64" -version = "0.17.1" +name = "generic-array" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa397a48544fadf0b81ec8741e5c0fba0043008113f71f2034def1935645d2b0" +checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" dependencies = [ - "dyn-stack 0.10.0", - "gemm-common 0.17.1", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 10.7.0", - "seq-macro", + "typenum", ] [[package]] -name = "gemm-f64" -version = "0.18.2" +name = "generic-array" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35b2a4f76ce4b8b16eadc11ccf2e083252d8237c1b589558a49b0183545015bd" +checksum = "f797e67af32588215eaaab8327027ee8e71b9dd0b2b26996aedf20c030fce309" dependencies = [ - "dyn-stack 0.13.2", - "gemm-common 0.18.2", - "num-complex", - "num-traits", - "paste", - "raw-cpuid 11.6.0", - "seq-macro", + "typenum", ] [[package]] name = "generic-array" -version = "0.14.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +checksum = "4bb6743198531e02858aeaea5398fcc883e71851fcbcb5a2f773e2fb6cb1edf2" dependencies = [ "typenum", "version_check", @@ -2607,70 +2608,120 @@ dependencies = [ [[package]] name = "geo" -version = "0.28.0" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fc1a1678e54befc9b4bcab6cd43b8e7f834ae8ea121118b0fd8c42747675b4a" +dependencies = [ + "earcutr", + "float_next_after", + "geo-types", + "geographiclib-rs", + "i_overlay", + "log", + "num-traits", + "robust", + "rstar 0.12.2", + "serde", + "spade", +] + +[[package]] +name = "geo" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f811f663912a69249fa620dcd2a005db7254529da2d8a0b23942e81f47084501" +checksum = "3f3901269ec6d4f6068d3f09e5f02f995bd076398dcd1dfec407cd230b02d11b" dependencies = [ "earcutr", "float_next_after", "geo-types", "geographiclib-rs", + "i_overlay", "log", "num-traits", + "rand 0.8.6", "robust", - "rstar", + "rstar 0.12.2", "serde", + "sif-itree", "spade", ] [[package]] name = "geo-types" -version = "0.7.17" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75a4dcd69d35b2c87a7c83bce9af69fd65c9d68d3833a0ded568983928f3fc99" +checksum = "94776032c45f950d30a13af6113c2ad5625316c9abfbccee4dd5a6695f8fe0f5" dependencies = [ - "approx 0.5.1", + "approx", "num-traits", - "rstar", + "rayon", + "rstar 0.10.0", + "rstar 0.11.0", + "rstar 0.12.2", + "rstar 0.8.4", + "rstar 0.9.3", "serde", ] [[package]] name = "geographiclib-rs" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f611040a2bb37eaa29a78a128d1e92a378a03e0b6e66ae27398d42b1ba9a7841" +checksum = "c5a7f08910fd98737a6eda7568e7c5e645093e073328eeef49758cfe8b0489c7" dependencies = [ "libm", ] +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + [[package]] name = "getrandom" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" dependencies = [ "cfg-if", "js-sys", "libc", - "wasi 0.11.1+wasi-snapshot-preview1", + "wasi", "wasm-bindgen", ] [[package]] name = "getrandom" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", "js-sys", "libc", - "r-efi", - "wasi 0.14.4+wasi-0.2.4", + "r-efi 5.3.0", + "wasip2", "wasm-bindgen", ] +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasip2", + "wasip3", +] + [[package]] name = "getset" version = "0.1.6" @@ -2680,7 +2731,7 @@ dependencies = [ "proc-macro-error2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -2693,12 +2744,6 @@ dependencies = [ "polyval", ] -[[package]] -name = "gimli" -version = "0.31.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" - [[package]] name = "glob" version = "0.3.3" @@ -2718,9 +2763,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.12" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3c0b69cfcb4e1b9f1bf2f53f95f766e4661169728ec61cd3fe5a0166f2d1386" +checksum = "171fefbc92fe4a4de27e0698d6a5b392d6a0e333506bc49133760b3bcf948733" dependencies = [ "atomic-waker", "bytes", @@ -2728,25 +2773,84 @@ dependencies = [ "futures-core", "futures-sink", "http", - "indexmap 2.11.0", + "indexmap", "slab", "tokio", "tokio-util", "tracing", ] +[[package]] +name = "h3" +version = "0.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10872b55cfb02a821b69dc7cf8dc6a71d6af25eb9a79662bec4a9d016056b3be" +dependencies = [ + "bytes", + "fastrand", + "futures-util", + "http", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "h3-datagram" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2c9f77921668673721ae40f17c729fc48b9e38a663858097cea547484fdf0f" +dependencies = [ + "bytes", + "h3", + "pin-project-lite", +] + +[[package]] +name = "h3-quinn" +version = "0.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2e732c8d91a74731663ac8479ab505042fbf547b9a207213ab7fbcbfc4f8b4" +dependencies = [ + "bytes", + "futures", + "h3", + "h3-datagram", + "quinn", + "tokio", + "tokio-util", +] + [[package]] name = "half" -version = "2.6.0" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ "bytemuck", "cfg-if", "crunchy", "num-traits", - "rand 0.9.2", + "rand 0.9.4", "rand_distr", + "zerocopy", +] + +[[package]] +name = "hash32" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4041af86e63ac4298ce40e5cca669066e75b6f1aa3390fe2561ffa5e1d9f4cc" +dependencies = [ + "byteorder", +] + +[[package]] +name = "hash32" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c35f58762feb77d74ebe43bdbc3210f09be9fe6742234d573bacc26ed92b67" +dependencies = [ + "byteorder", ] [[package]] @@ -2778,19 +2882,36 @@ name = "hashbrown" version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash", + "foldhash 0.2.0", + "serde", + "serde_core", ] +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + [[package]] name = "hashlink" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1" +checksum = "ea0b22561a9c04a7cb1a302c013e0259cd3b4bb619f145b32f72b8b4bcbed230" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", ] [[package]] @@ -2817,16 +2938,47 @@ dependencies = [ "http", ] +[[package]] +name = "heapless" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634bd4d29cbf24424d0a4bfcbf80c6960129dc24424752a7d1d1390607023422" +dependencies = [ + "as-slice", + "generic-array 0.14.9", + "hash32 0.1.1", + "stable_deref_trait", +] + +[[package]] +name = "heapless" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdc6457c0eb62c71aac4bc17216026d8410337c4126773b9c5daba343f17964f" +dependencies = [ + "atomic-polyfill", + "hash32 0.2.1", + "rustc_version", + "spin", + "stable_deref_trait", +] + [[package]] name = "heapless" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad" dependencies = [ - "hash32", + "hash32 0.3.1", "stable_deref_trait", ] +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + [[package]] name = "heck" version = "0.5.0" @@ -2854,16 +3006,16 @@ dependencies = [ "dirs", "futures", "http", - "indicatif", + "indicatif 0.17.11", "libc", "log", "native-tls", "num_cpus", - "rand 0.9.2", - "reqwest", + "rand 0.9.4", + "reqwest 0.12.28", "serde", "serde_json", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "ureq", "windows-sys 0.60.2", @@ -2903,18 +3055,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "55d958c2f74b664487a2035fe1dadb032c48718a03b63f3ab0b8537db8549ed4" dependencies = [ "log", - "markup5ever", + "markup5ever 0.35.0", "match_token", ] +[[package]] +name = "html5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6452c4751a24e1b99c3260d505eaeee76a050573e61f30ac2c924ddc7236f01e" +dependencies = [ + "log", + "markup5ever 0.36.1", +] + [[package]] name = "http" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" +checksum = "8be7462df143984c4598a256ef469b251d7d7f9e271135073e78fc535414f3d0" dependencies = [ "bytes", - "fnv", "itoa", ] @@ -2955,15 +3116,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b112acc8b3adf4b107a8ec20977da0273a8c386765a3ec0229bd500a1443f9f" +checksum = "135b12329e5e3ce057a9f972339ea52bc954fe1e9358ef27f95e89716fbc5424" [[package]] name = "hyper" -version = "1.7.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" dependencies = [ "atomic-waker", "bytes", @@ -2976,7 +3137,6 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "pin-utils", "smallvec", "tokio", "want", @@ -2984,9 +3144,9 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.27.7" +version = "0.27.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" dependencies = [ "http", "hyper", @@ -2994,11 +3154,22 @@ dependencies = [ "log", "rustls", "rustls-native-certs", - "rustls-pki-types", "tokio", "tokio-rustls", "tower-service", - "webpki-roots 1.0.2", +] + +[[package]] +name = "hyper-timeout" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" +dependencies = [ + "hyper", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", ] [[package]] @@ -3019,14 +3190,13 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.16" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ "base64 0.22.1", "bytes", "futures-channel", - "futures-core", "futures-util", "http", "http-body", @@ -3043,11 +3213,54 @@ dependencies = [ "windows-registry", ] +[[package]] +name = "i_float" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "010025c2c532c8d82e42d0b8bb5184afa449fa6f06c709ea9adcb16c49ae405b" +dependencies = [ + "libm", +] + +[[package]] +name = "i_key_sort" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9190f86706ca38ac8add223b2aed8b1330002b5cdbbce28fb58b10914d38fc27" + +[[package]] +name = "i_overlay" +version = "4.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413183068e6e0289e18d7d0a1f661b81546e6918d5453a44570b9ab30cbed1b3" +dependencies = [ + "i_float", + "i_key_sort", + "i_shape", + "i_tree", + "rayon", +] + +[[package]] +name = "i_shape" +version = "1.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ea154b742f7d43dae2897fcd5ead86bc7b5eefcedd305a7ebf9f69d44d61082" +dependencies = [ + "i_float", +] + +[[package]] +name = "i_tree" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35e6d558e6d4c7b82bc51d9c771e7a927862a161a7d87bf2b0541450e0e20915" + [[package]] name = "iana-time-zone" -version = "0.1.63" +version = "0.1.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -3055,7 +3268,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core 0.61.2", + "windows-core 0.62.2", ] [[package]] @@ -3069,22 +3282,23 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47" +checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" dependencies = [ "displaydoc", "potential_utf", - "yoke 0.8.0", + "utf8_iter", + "yoke", "zerofrom", "zerovec", ] [[package]] name = "icu_locale_core" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a" +checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" dependencies = [ "displaydoc", "litemap", @@ -3095,11 +3309,10 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979" +checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" dependencies = [ - "displaydoc", "icu_collections", "icu_normalizer_data", "icu_properties", @@ -3110,49 +3323,51 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3" +checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" [[package]] name = "icu_properties" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b" +checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" dependencies = [ - "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", "icu_provider", - "potential_utf", "zerotrie", "zerovec", ] [[package]] name = "icu_properties_data" -version = "2.0.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632" +checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" [[package]] name = "icu_provider" -version = "2.0.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af" +checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" dependencies = [ "displaydoc", "icu_locale_core", - "stable_deref_trait", - "tinystr", "writeable", - "yoke 0.8.0", + "yoke", "zerofrom", "zerotrie", "zerovec", ] +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + [[package]] name = "ident_case" version = "1.0.1" @@ -3172,9 +3387,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -3182,9 +3397,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.8" +version = "0.25.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529feb3e6769d234375c4cf1ee2ce713682b8e76538cb13f9fc23e1400a591e7" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", @@ -3214,44 +3429,41 @@ dependencies = [ "quote", ] -[[package]] -name = "indenter" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" - [[package]] name = "indexmap" -version = "1.9.3" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ - "autocfg", - "hashbrown 0.12.3", + "equivalent", + "hashbrown 0.17.1", "serde", + "serde_core", ] [[package]] -name = "indexmap" -version = "2.11.0" +name = "indicatif" +version = "0.17.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" dependencies = [ - "equivalent", - "hashbrown 0.15.5", - "serde", + "console 0.15.11", + "number_prefix", + "portable-atomic", + "unicode-width", + "web-time", ] [[package]] name = "indicatif" -version = "0.17.11" +version = "0.18.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "183b3088984b400f4cfac3620d5e076c84da5364016b4f49473de574b2586235" +checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ - "console", - "number_prefix", + "console 0.16.3", "portable-atomic", - "unicode-width 0.2.1", + "unicode-width", + "unit-prefix", "web-time", ] @@ -3261,7 +3473,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" dependencies = [ - "generic-array", + "generic-array 0.14.9", ] [[package]] @@ -3288,51 +3500,24 @@ dependencies = [ [[package]] name = "inventory" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc61209c082fbeb19919bee74b176221b27223e27b65d781eb91af24eb1fb46e" +checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b" dependencies = [ "rustversion", ] [[package]] name = "ipnet" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" - -[[package]] -name = "iri-string" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" -dependencies = [ - "memchr", - "serde", -] - -[[package]] -name = "is-terminal" -version = "0.4.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.59.0", -] - -[[package]] -name = "is_ci" -version = "1.2.0" +version = "2.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" [[package]] name = "is_terminal_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] name = "itertools" @@ -3372,9 +3557,58 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.15" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror 2.0.18", + "walkdir", + "windows-link 0.2.1", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.117", +] [[package]] name = "jobserver" @@ -3382,16 +3616,18 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", "libc", ] [[package]] name = "js-sys" -version = "0.3.78" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0b063578492ceec17683ef2f8c5e89121fbd0b172cbc280635ab7567db2738" +checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11" dependencies = [ + "cfg-if", + "futures-util", "once_cell", "wasm-bindgen", ] @@ -3409,71 +3645,27 @@ dependencies = [ [[package]] name = "jsonwebtoken" -version = "9.3.1" +version = "10.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a87cc7a48537badeae96744432de36f4be2b4a34a05a5ef32e9dd8a1c169dde" -dependencies = [ - "base64 0.22.1", - "js-sys", - "pem", - "ring", - "serde", - "serde_json", - "simple_asn1", -] - -[[package]] -name = "jsonwebtoken" -version = "10.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d119c6924272d16f0ab9ce41f7aa0bfef9340c00b0bb7ca3dd3b263d4a9150b" +checksum = "eba32bfb4ffdeaca3e34431072faf01745c9b26d25504aa7a6cf5684334fc4fc" dependencies = [ + "aws-lc-rs", "base64 0.22.1", "ed25519-dalek", - "getrandom 0.2.16", + "getrandom 0.2.17", "hmac", "js-sys", "p256", "p384", "pem", - "rand 0.8.5", + "rand 0.8.6", "rsa", "serde", "serde_json", "sha2 0.10.9", "signature", "simple_asn1", -] - -[[package]] -name = "lalrpop" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55cb077ad656299f160924eb2912aa147d7339ea7d69e1b5517326fdcec3c1ca" -dependencies = [ - "ascii-canvas", - "bit-set", - "ena", - "itertools 0.11.0", - "lalrpop-util", - "petgraph", - "pico-args", - "regex", - "regex-syntax", - "string_cache", - "term", - "tiny-keccak", - "unicode-xid", - "walkdir", -] - -[[package]] -name = "lalrpop-util" -version = "0.20.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507460a910eb7b32ee961886ff48539633b788a36b65692b95f225b844c82553" -dependencies = [ - "regex-automata", + "zeroize", ] [[package]] @@ -3486,13 +3678,10 @@ dependencies = [ ] [[package]] -name = "lexicmp" +name = "leb128fmt" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7378d131ddf24063b32cbd7e91668d183140c4b3906270635a4d633d1068ea5d" -dependencies = [ - "any_ascii", -] +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "lexicmp" @@ -3505,71 +3694,65 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.175" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "libloading" -version = "0.8.8" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-targets 0.53.3", + "windows-link 0.2.1", ] [[package]] name = "libm" -version = "0.2.15" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + +[[package]] +name = "libmimalloc-sys" +version = "0.1.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de" +checksum = "6a45a52f43e1c16f667ccfe4dd8c85b7f7c204fd5e3bf46c5b0db9a5c3c0b8e9" +dependencies = [ + "cc", +] [[package]] name = "libredox" -version = "0.1.9" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3" +checksum = "f02ab6bace2054fb888a3c16f990117b579d14a3088e472d63c6011fa185c9d3" dependencies = [ - "bitflags 2.9.4", "libc", - "redox_syscall", ] [[package]] name = "libz-sys" -version = "1.1.22" +version = "1.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b70e7a7df205e92a1a4cd9aaae7898dac0aa555503cc0a649494d0d60e7651d" +checksum = "85bc9657773828b90eeb625adff10eeac83cc21bbfd8e23a03eaa8a33c9e28d9" dependencies = [ "cc", "pkg-config", "vcpkg", ] -[[package]] -name = "linfa-linalg" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e7562b41c8876d3367897067013bb2884cc78e6893f092ecd26b305176ac82" -dependencies = [ - "ndarray", - "num-traits", - "rand 0.8.5", - "thiserror 1.0.69", -] - [[package]] name = "lingua" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e501c98d473068ce13ddfa5ca86846a6b60e24e3020ba9d2f49af654e9219ec" +checksum = "f40d9129bb9fe42c95d1bd420d6891607eaff17df16ee15674aed2d05b0ec8f4" dependencies = [ - "ahash 0.8.12", - "brotli", - "compact_str", - "dashmap 6.1.0", - "fraction", + "counter", + "dashmap", + "fastrand", + "fst", "include_dir", "itertools 0.14.0", "lingua-afrikaans-language-model", @@ -3652,7 +3835,6 @@ dependencies = [ "regex", "serde", "serde-wasm-bindgen", - "serde_json", "strum 0.27.2", "strum_macros 0.27.2", "wasm-bindgen", @@ -3660,727 +3842,716 @@ dependencies = [ [[package]] name = "lingua-afrikaans-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1287f2382e4505a9884982a208129fa0f19d331c819667ac0396e3435ffca176" +checksum = "2810a47263f58358fa22acc425b330a334382f33fcee8f205be672a7ec6d8d4a" dependencies = [ "include_dir", ] [[package]] name = "lingua-albanian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2843d913f39870c0226ada84959d1f796b12f10db0e4b9cdcc9588df8dcc4fe3" +checksum = "81be672350a5a37c9aae935dd8520295289cc02d098929484b963b60fb42e174" dependencies = [ "include_dir", ] [[package]] name = "lingua-arabic-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a54f30346c57deb114fc9083047a441fc9a0fca5dd4b11db82a96ac04d4c3c53" +checksum = "5bcc254ff44209c2a50dea58a644f9c257a0aa5cd7e1739fd9c373fe4c7456cf" dependencies = [ "include_dir", ] [[package]] name = "lingua-armenian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1582c3543a18d82ddd747e77ecca9ca0c6c344bbb85aa9aeafe4afaf4c674396" +checksum = "4cf4e5825cb3a2b11d8bd7baa6788167b65ffbf8ce21dc9b9dcb5e6adee1d5f0" dependencies = [ "include_dir", ] [[package]] name = "lingua-azerbaijani-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d955c944289ef7919710c181575c93401732e08a1d2c901d2e0171748ddb9c39" +checksum = "3fdcc775ff75bcc6de0ea5330f65e62644622e29c980a72b437780ba57bba838" dependencies = [ "include_dir", ] [[package]] name = "lingua-basque-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c04f4beb9512e0b1bb9d44bd51cc012ca075a88a8773dc971a22900e9b43db4" +checksum = "5cbea869a4556800f2798c61559fd2e87fd65d7698ce27ad6fba5b1d9ec1fbe9" dependencies = [ "include_dir", ] [[package]] name = "lingua-belarusian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6a22cafc7351c8f4ebb48dd4f513f0bb4d1b9bd4a5d38f4955bfa35e378f0b" +checksum = "2887044d4c11388e15692bf953f70468282600c426e1cd6a208a93aeca3aedfd" dependencies = [ "include_dir", ] [[package]] name = "lingua-bengali-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad51861506bf06428b95c90662803700f365331959b3007bde47aaaacfbcd5ac" +checksum = "7f94131563e0e0c571cebf03f867d0e1b7dd15278f7cab3e4ba8b0f8026072cc" dependencies = [ "include_dir", ] [[package]] name = "lingua-bokmal-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d10116c60af75f59d61058f7402fe866af56c18c1c69b363fb9c4ee28f7f555c" +checksum = "b443b1ec0498bcf43594f9bf65ae8f5660b5bf21eb769950a245ced8e376ac23" dependencies = [ "include_dir", ] [[package]] name = "lingua-bosnian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b0ba20e4fc22116b6e3873d1d15fbc5c6371de12b5f5a4fa4f583f37328521d7" +checksum = "04f540ed0441bcdbb0b36c43f306bc2b0892921ceb95e865fe0b8b0c39bb82c4" dependencies = [ "include_dir", ] [[package]] name = "lingua-bulgarian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf7243e09160b87a4b4543747e7ea4549cbf022538a493af93e8633da9ad97c" +checksum = "2f4679441ff2d94b21a3d76293ffd5310a012ea62247b7b2066939e2728cbfc0" dependencies = [ "include_dir", ] [[package]] name = "lingua-catalan-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71aa462a7c191e75c3949f8a7beca9031d188e8ea28f2eb76c99b2d526927d21" +checksum = "7366ac180de87eb19f32063b8eed1db270ab333f7a450d96250e53b14b0a750f" dependencies = [ "include_dir", ] [[package]] name = "lingua-chinese-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d31600b0cbae8a5c0622038d90e7d3830193d78feb2741f8678267d9f76e90f0" +checksum = "21ca7fa9f7671d684c82c168725f380fc873f14d6f4e8c82f0da681bcc0048d1" dependencies = [ "include_dir", ] [[package]] name = "lingua-croatian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7438e2753dc02a1dd0c355afd1399ce26fbc13205454d81ed611e249987f134" +checksum = "d86b1346b98397e7cf87e8f3fe544fce6514918e6bde253a014eea7ca03c31d8" dependencies = [ "include_dir", ] [[package]] name = "lingua-czech-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e1b3749cb0a0e40f7a732d1ae9b8cb4bf35444e92a2dd7db9164971e4157c9c" +checksum = "348f06e4f90e1c2bc597ea3caf52abb9d3dd09ba227fa7cf4f2dc723a9810e98" dependencies = [ "include_dir", ] [[package]] name = "lingua-danish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9f83ef0885a702e6ddf776473f0eea13e3b7c20bac94ec4245cfabec555143e" +checksum = "363953413132601a06fe0cae1fffb5d519d0cfb378049cc78b3893edd03a194f" dependencies = [ "include_dir", ] [[package]] name = "lingua-dutch-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f390bbffcb405f9a36fbb014cfd1953f2a5edc0b4313ca2005aba51e6ed6741" +checksum = "fe0da523f4726c05ed557b5a309315c1c161a5ec9ca6036c6c1c799ce492b698" dependencies = [ "include_dir", ] [[package]] name = "lingua-english-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a4b2666c2dc3669b9cc2235f318184f3cc3426bf7075336bcf8f9ddba6f81c0" +checksum = "97102de08b134a49f1cce05a1b6f5bf08ef21fe858074ae2b794e7892c43dd4b" dependencies = [ "include_dir", ] [[package]] name = "lingua-esperanto-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f169804327d4ae648c9045e139e19f2c1a8426cd2afcad6db9223d6de3cd3855" +checksum = "13d2a7ae84bfa3ed2a05815ca4a81d34cee7da1a77e830ab933c4debc21d6532" dependencies = [ "include_dir", ] [[package]] name = "lingua-estonian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b675de6a28fc39d7af5b19240ad2c34dc5646b1d1ef812cb93c6b2c589cd13d6" +checksum = "7095f107a6e89147a9066db6a3f9e1b0a4706323d59a4bb58fa8218d74c1fde8" dependencies = [ "include_dir", ] [[package]] name = "lingua-finnish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bc6109e57ed65b665ee7f911ed451cd6587304a0bfda9359c8794c33dffc425" +checksum = "f5b3c44089812704148c89dbe77fb34122c2f6e8182bbf0f72ea69c92e948e9e" dependencies = [ "include_dir", ] [[package]] name = "lingua-french-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fd27da82335b66738d137ee64221f479973467b9178d49d802acbe847de355" +checksum = "45508227e42c9cc5eb202e17c4c40e38ea7b9be9421faeb3ab0fb7ac37d9c681" dependencies = [ "include_dir", ] [[package]] name = "lingua-ganda-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd847988a427b3f6b9bd39bcc271643edf190c1608eff2a3c4208f717c66752a" +checksum = "f7d4b9fba87a72ae0f929fbe0bdc78f71be78d14475219718e70fd686b281082" dependencies = [ "include_dir", ] [[package]] name = "lingua-georgian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c91bb5d3f24e8760a1411d0c5868b8e614ecb7b480328c7dcea4fc1b4b7201" +checksum = "73f3568595e73295b905ec54cc2dbda915efaee5f7abf91d572e9d44a843e81d" dependencies = [ "include_dir", ] [[package]] name = "lingua-german-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa568bbca8beb3b0cfc691cf2e87d1d24cb457c8e19ed168dd22d739c24a15e" +checksum = "f584da803e8c135ea22dd3ed321a6b3e2ff3465559606be0a597924ecd465cb2" dependencies = [ "include_dir", ] [[package]] name = "lingua-greek-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b473b60c61e0aee31bdd2cf35642942dde8dcfd7b1ea4c7534df98994c3b429f" +checksum = "a5da9a688ceb41963f3555526a2e4431e0e5208a3320e56b72b1de998ba6b1c7" dependencies = [ "include_dir", ] [[package]] name = "lingua-gujarati-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc48e1164860f35cac2ff6f3369d7c2e36feef54bd5eb6cafd32ba5fc7ad63d" +checksum = "e495d0421f5e4d6b1d71ebf3a98b445c5ada6b03f033b6b62db2382e4d075663" dependencies = [ "include_dir", ] [[package]] name = "lingua-hebrew-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c36ff9bfba287adc3a05cd6ca2a512412155d0fbfd1f4eaddcf800f42fe3d9" +checksum = "fc49d9a174de884bba595c8b575ee37fdb1c1a728eeff608d43e1a7378048545" dependencies = [ "include_dir", ] [[package]] name = "lingua-hindi-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0930f8845e398914d0f4b25342774b199f6486971c79fd225fd0f3f747b8d2" +checksum = "dca88af8dede1a30fcd79318b9c22f3662785fd87ed5b39881d19770651bf720" dependencies = [ "include_dir", ] [[package]] name = "lingua-hungarian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "286a84ab04128d25fadb162d852a327d32174ab16b7ab4725e4047820b92a781" +checksum = "0d7072b2cdf43438214e82b53c51ad85a16d657e5c07a5a77bef78a4cd39423c" dependencies = [ "include_dir", ] [[package]] name = "lingua-icelandic-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "499bfe35307f587a18c3c8492debb84c3b8cab733035b6852cdf0bf508b6d99f" +checksum = "341fa17414af93a6ccf33c6efda9e65d1476a18785b075a16d53f66c9e19379d" dependencies = [ "include_dir", ] [[package]] name = "lingua-indonesian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1eb4112ce3f4c5d24d739c047e6d815a4ed283ccf71a47669f6f2132e36b5c7a" +checksum = "fe1f2e05145c3fb4172c01c4563f729938c85f77742948444523dfcda2c3e80d" dependencies = [ "include_dir", ] [[package]] name = "lingua-irish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a90343c0e74060362793a19a7139f58533f9be61156805fab635ad5cfc5378" +checksum = "5099708a7fc7081e4171dbc0905691e5e02639d8899558a105720f28522261db" dependencies = [ "include_dir", ] [[package]] name = "lingua-italian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab586cc7454f4df2a224ce245f81e199dba57d47259fc628b29d5c066697059" +checksum = "83a87385ee42f6a0306df81066d4f77c225a337137fc15978a4b319c6bcf4bfe" dependencies = [ "include_dir", ] [[package]] name = "lingua-japanese-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5756b671f8a2f0ba8ae81852ab44d38485e60c590cacdff23400c47a48d04244" +checksum = "df0938f75de3ae5dcdc925d823ed409854ca14f6a653782b9a1ad5d899462fbe" dependencies = [ "include_dir", ] [[package]] name = "lingua-kazakh-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccbe5bbdb753152eb3c3cb6d37df58c81c12e57122898286fc1b17ad5667f419" +checksum = "af90d71a099b11f3b0677402a9894e95b0acb9459343735dfaec57af6be11ee6" dependencies = [ "include_dir", ] [[package]] name = "lingua-korean-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b30b14af9b0f1335e6117d63b6a71afac660f4c83e81a8fd593a963222cc1b9c" +checksum = "aa87f6c43ff894fc75159c021480d2fdf96882bf5bd235f8916ceb6b7caae561" dependencies = [ "include_dir", ] [[package]] name = "lingua-latin-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f02abfb6beb5c53b345a3e599c9faeff3e765cf6f79b77f6650585967568c5e" +checksum = "757c1330e893bc532559397d976656a7bb0a42f391f7c946727ffb43a3761e46" dependencies = [ "include_dir", ] [[package]] name = "lingua-latvian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef790c9c49220157d09f007b9c4ae0adb7b3ffe33e3aa6c0bcdc81cd995b919a" +checksum = "f1b2f30766e9e1ce10d960ce3eb2da6514fd0ee18c8d617a566b03126140e656" dependencies = [ "include_dir", ] [[package]] name = "lingua-lithuanian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d546fe945b7bc4c5879fb7e59c589396277e3f007972391e55730940ffe4ef03" +checksum = "4e4a2a1994e48841c1d2d63099fbd68476615bf0d833fa14a3654f7043e38fc7" dependencies = [ "include_dir", ] [[package]] name = "lingua-macedonian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6368874d9d400cc3efc5d74de6c66fa5ebbf89589523e1995420ba2fd677359" +checksum = "779ea3952ecade3aff6a34eea6f432a0d10652fafd9723a1b2258551b08f83b4" dependencies = [ "include_dir", ] [[package]] name = "lingua-malay-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c003d235500af772243973dfcd26cc077e850308b6da873cac365b1c91fce3af" +checksum = "10936b2ac22076f9dbb968c71aacbf16c71ed36a92da10f077850d7ec5ded341" dependencies = [ "include_dir", ] [[package]] name = "lingua-maori-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0aa75bfac8296dc681b3d9abbeb62b3bee925893d48070ac3ec87858e539f6" +checksum = "d5bbc1e34392b0081209eec7d6b201a062612717c0670dad451066d9026261da" dependencies = [ "include_dir", ] [[package]] name = "lingua-marathi-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89511520fae381b87e25153ac5b08146d8fe91b11650433cd6fba60cff342bdb" +checksum = "fb68fa15d9a57a2ca2a71f8f59f455267bd8a8793216449697c2dd04898915a0" dependencies = [ "include_dir", ] [[package]] name = "lingua-mongolian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4983ac733c95c8e12917f3db984c6f02b41587acac22ca9b4f37cf6cc32a8a52" +checksum = "a72e6a2a3c9ecb22dbd8870bae40c167f767defd69f05c58e5467d233b6360d5" dependencies = [ "include_dir", ] [[package]] name = "lingua-nynorsk-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ee1fa246487b683138da7684035489ab5fafb2751d0715b33c38f6a6eadb5f" +checksum = "2f5e7e54f8e04a5286aab3a8e22f395b42e9341cab1fdafdd04660a17e81fe8d" dependencies = [ "include_dir", ] [[package]] name = "lingua-persian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29a97bc46fe85d9f06d50668615eb903b1e7ed77dad228dac98228d417c6e84d" +checksum = "ddf084e05d33ed66d64461e6397b571fdf74fe93c13c4ac4c84a633e33d2d07b" dependencies = [ "include_dir", ] [[package]] name = "lingua-polish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1534fd0f8c717bffd9ec80e9b27b8627fa069b46e9474b0e29780eb5fdddb53f" +checksum = "72eb03e7940b3178c152138a16976e374ed0a3ddc80dc6f0b56984ab1189cb67" dependencies = [ "include_dir", ] [[package]] name = "lingua-portuguese-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3659ec08115bbec9151bc23e62a4c3ee768c138e791854c8fe71cfcde0e5de84" +checksum = "432eda7984456055033ffa168037be9afe0f5c9ecd891bf5f27435247d496b47" dependencies = [ "include_dir", ] [[package]] name = "lingua-punjabi-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e165678767e73db517e9aeb43817517b28f5b31d13f20853847bc8f05a1ae3bd" +checksum = "620ec0c678bfca1b99d5379f8024cfed24149556a0d55957799d870f3c71df26" dependencies = [ "include_dir", ] [[package]] name = "lingua-romanian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836d7f9116c098e863c05dbb4739df77c516485b5e3f2e9457d376ba83834183" +checksum = "1051aa082754acfc52110456e29fbbf6d2c648da9a4753a861c34f19325cfab8" dependencies = [ "include_dir", ] [[package]] name = "lingua-russian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9058ef9a1b6d09727f63c8831c38d81c09456a2b433e4d02aa296ef83c19b631" +checksum = "4fc0850578299531b50192be2c1de1af651f1289784253645e737fe456a6a138" dependencies = [ "include_dir", ] [[package]] name = "lingua-serbian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a106952e53e9162c8a96bd9eea9b1874df5ace221bac1ab7868528b4b37e78" +checksum = "df46949714d864f81138b3590878c89f06cf5d0af0e758a1e1217dd13983a896" dependencies = [ "include_dir", ] [[package]] name = "lingua-shona-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924047ff3712b3ed640e0e950faf6e5682ee57592a141da6ae5a149b44451c38" +checksum = "85ca30d90634fc427e79dddfa555524f5983a630ce809aeb02b708f434937965" dependencies = [ "include_dir", ] [[package]] name = "lingua-slovak-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44afb5363903e2c6b10b8dc14f9b3c4abc1e125ecb4763ab189382a951e8f1f2" +checksum = "529a596f3d90b2051b3ead90e864f6ad9e14b43716c3f252268e9e6e43ab28de" dependencies = [ "include_dir", ] [[package]] name = "lingua-slovene-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd43bd4567a3bffa3d20b3e2c62e3a3d17988c34948df88353d59eebcdcb5a3d" +checksum = "db52978574611533d873b727281d1c1d0ab2b031331654c1729723b682bc76a1" dependencies = [ "include_dir", ] [[package]] name = "lingua-somali-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a912003628ee6b007b6aca330aefa1cf67369f7d9e2c925e38e66e058abe070" +checksum = "be79a11e6d682c7f1ecb342fe41169a59d6adb5eac3b4de77973fb7bbf936e39" dependencies = [ "include_dir", ] [[package]] name = "lingua-sotho-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fd83a7172be44cd2fc7a630b96b3d9ba1a07cbe295937e19b94dcba2144502" +checksum = "c476a7019592446989258b7f204cc7b5429b42a4d7eb686b80461a5f790e08bc" dependencies = [ "include_dir", ] [[package]] name = "lingua-spanish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05df7766652773b2292e7ad12221c0090954baed18ca2ff631a5f134ce08d91d" +checksum = "56395a8d96c892130a9efb433c5f042977fb75ae5fb6e0058c8814a947459137" dependencies = [ "include_dir", ] [[package]] name = "lingua-swahili-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc6a2e6ec74d0de7409e81a4ecac90fc061c87f397e9358c1fc7b06fb71375b1" +checksum = "218763c238936496b53d88535e1a4db1eda30c278af682f02d6b836edb08162a" dependencies = [ "include_dir", ] [[package]] name = "lingua-swedish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0abcbfc81c994fa2e433571febecbf7a3011c1f46164d7ca5013691656c9b3" +checksum = "77c965c5b11d6e1e619a98e393d16f73a0754cb05b5b067b537fd25e9b74bec0" dependencies = [ "include_dir", ] [[package]] name = "lingua-tagalog-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0275f0d641f8193aba7dabe8ced95a7b12e14a9652bb9b3067b95861472be791" +checksum = "fe7e48a2d97dc20ebe3618c794d45c363299e4930cc2ff2fd21b174130d75e8d" dependencies = [ "include_dir", ] [[package]] name = "lingua-tamil-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8badccb67d6eec015563538ffcfa6d2a6ff151bcb787ce0d24097c26d410e07" +checksum = "212e6ed4c50fc9b06278f5b401ba17eeece43ccc84515e95ece76efd16e55d9b" dependencies = [ "include_dir", ] [[package]] name = "lingua-telugu-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "828376db1408126c403656447eaceaede6f39c20d81f78a3c32e6cb9d78ceb20" +checksum = "af1a68d768b356c89f0a68280ab9a4adec487ba3b0ba1d2dda244a86ed712797" dependencies = [ "include_dir", ] [[package]] name = "lingua-thai-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f72427dd733f84054777b8c229d489766a880b5e5207c0bc57f8983423256b" +checksum = "2582eeabf02e39680856c3f88d3b93fcdb351009407d38a4735326c8b0a33bce" dependencies = [ "include_dir", ] [[package]] name = "lingua-tsonga-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac4de2ed21a6e3a82a66a712fbaddfb150846eefa6cde4f8b33d732e6debe89d" +checksum = "86e34d4bff2ed22b8b666b67a9a019c94fc01097764d7d7bc0a4f943abf88efd" dependencies = [ "include_dir", ] [[package]] name = "lingua-tswana-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1164e518ba79371e8d10801bdc48ba704f9260cbc45a45d0bf8710d860382369" +checksum = "9aa7f52c30b53ed63ac9bf9ddefaf746c983e668f917f4133d4cda39a009b7e1" dependencies = [ "include_dir", ] [[package]] name = "lingua-turkish-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10e15e6c8aa9c7b807933aa257468309c9ae41b84898fd087356dea4aa0ec036" +checksum = "2a2ab6b46c596ebd7f58e0db7a3d732c42a2fa48b77094a0737e920a5c47dca0" dependencies = [ "include_dir", ] [[package]] name = "lingua-ukrainian-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3509a5a27c043e76c31a9c8a5a16deb3dc6e1fd26de029cb83b20d16ca1fe2" +checksum = "b86175a68d53b3b1e3aaf2e2fa61d31e8f03df7e0fcb51d7e1dd62fce86cb393" dependencies = [ "include_dir", ] [[package]] name = "lingua-urdu-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13b529ccb188dddd222c613b71e86d9401cb5e5a46dbd62a867906da093fec64" +checksum = "1d308fdae7c8caa05ffe455e8a2e568e5f018cb2742f588a810ecf306b890622" dependencies = [ "include_dir", ] [[package]] name = "lingua-vietnamese-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "489ba31146a87c04a783bcca606b961320a9cace365378bd329933a8b3ae2f50" +checksum = "45ef9a92dce65c6e9fea7f2343e51de8b5b9cd764fa8ae3592c4ba3edd992d4a" dependencies = [ "include_dir", ] [[package]] name = "lingua-welsh-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f285d84e053c405a97a00e59a1e7aa82ac967a091d2de0f484322dd539c81080" +checksum = "1057abcd15da2c81baafe25cefa148b5b56d382d645af749084987e1a6d576e2" dependencies = [ "include_dir", ] [[package]] name = "lingua-xhosa-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3080b71235d1834423ef0e4c772e24f99699d427718efab67160792d7bd5984" +checksum = "d165e4dfe98f8ed1a9f768e5fefe13d472ad1c5600e7ceab6a1a4a942be4c2ee" dependencies = [ "include_dir", ] [[package]] name = "lingua-yoruba-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b8033c5058586fd180b1f42b2ece059c5cefb620703ecc92f379ac0a142194" +checksum = "6da42216997d892ce8822eae591084555469e1d32e44fe6e181996fb200492d3" dependencies = [ "include_dir", ] [[package]] name = "lingua-zulu-language-model" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9dfb5039e1f9268f2310277493a5dc44e9448e55e0f26938c8d1d8cd92f98c" +checksum = "e429650453aa15779df3560ce9150c1cdfa48bbb8975e95a925cf868b2a3dc0a" dependencies = [ "include_dir", ] [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" [[package]] name = "local-ip-address" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "656b3b27f8893f7bbf9485148ff9a65f019e3f33bd5cdc87c83cab16b3fd9ec8" +checksum = "aa08fb2b1ec3ea84575e94b489d06d4ce0cbf052d12acd515838f50e3c3d63e3" dependencies = [ "libc", "neli", - "thiserror 2.0.16", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] name = "lock_api" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" dependencies = [ - "autocfg", "scopeguard", ] [[package]] name = "log" -version = "0.4.28" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432" - -[[package]] -name = "lru" -version = "0.12.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" -dependencies = [ - "hashbrown 0.15.5", -] +checksum = "616ec5685824bcc94416c6d4a7a446eea774a31efd7062c8480ba6fd06d7a6e5" [[package]] name = "lru-slab" @@ -4388,6 +4559,15 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +[[package]] +name = "lz4" +version = "1.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a20b523e860d03443e98350ceaac5e71c6ba89aea7d960769ec3ce37f4de5af4" +dependencies = [ + "lz4-sys", +] + [[package]] name = "lz4-sys" version = "1.11.1+lz4-1.10.0" @@ -4424,7 +4604,10 @@ checksum = "670fdfda89751bc4a84ac13eaa63e205cf0fd22b4c9a5fbfa085b63c1f1d3a30" name = "macros" version = "0.2.0" dependencies = [ + "paste", + "proc-macros", "serde", + "serde_json", ] [[package]] @@ -4441,7 +4624,18 @@ checksum = "311fe69c934650f8f19652b3946075f0fc41ad8757dbb68f1ca14e7900ecc1c3" dependencies = [ "log", "tendril", - "web_atoms", + "web_atoms 0.1.3", +] + +[[package]] +name = "markup5ever" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c3294c4d74d0742910f8c7b466f44dda9eb2d5742c1e430138df290a1e8451c" +dependencies = [ + "log", + "tendril", + "web_atoms 0.2.4", ] [[package]] @@ -4452,7 +4646,7 @@ checksum = "ac84fd3f360fcc43dc5f5d186f02a94192761a080e8bc58621ad4d12296a58cf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -4464,6 +4658,12 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + [[package]] name = "matrixmultiply" version = "0.3.10" @@ -4486,41 +4686,52 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.5" +version = "2.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8" [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", "stable_deref_trait", ] [[package]] -name = "miette" -version = "5.10.0" +name = "memo-map" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59bb584eaeeab6bd0226ccf3509a69d7936d148cf3d036ad350abe35e8c6856e" +checksum = "38d1115007560874e373613744c6fba374c17688327a71c1476d1a5954cc857b" + +[[package]] +name = "migrations-tool" +version = "0.2.0" dependencies = [ - "miette-derive", - "once_cell", - "thiserror 1.0.69", - "unicode-width 0.1.14", + "async-stream", + "blake2", + "chrono", + "clap", + "futures", + "serde", + "serde_json", + "snafu", + "surrealdb", + "tempfile", + "tokio", + "tracing", + "tracing-subscriber", ] [[package]] -name = "miette-derive" -version = "5.10.0" +name = "mimalloc" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" +checksum = "2d4139bb28d14ad1facf21d5eb8825051b326e172d216b39f6d31df53cc97862" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "libmimalloc-sys", ] [[package]] @@ -4531,9 +4742,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime-infer" -version = "4.0.0" +version = "4.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d72eb6076a2d5a9c624f9282d5a4d3428303c7c6671067f8ef812d91a002710" +checksum = "a10bc91d55685b82739d1dc95ec6e40485695cfe07b0a3abc1a82df17c40a0e5" dependencies = [ "mime", "unicase", @@ -4549,6 +4760,16 @@ dependencies = [ "unicase", ] +[[package]] +name = "minijinja" +version = "2.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2929e494b2280e1e18959bb2e121da03347ae896896fdfaceaab43c88a02803f" +dependencies = [ + "memo-map", + "serde", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -4567,13 +4788,13 @@ dependencies = [ [[package]] name = "mio" -version = "1.0.4" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" +checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" dependencies = [ "libc", - "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys 0.59.0", + "wasi", + "windows-sys 0.61.2", ] [[package]] @@ -4595,14 +4816,14 @@ checksum = "e4db6d5580af57bf992f59068d4ea26fd518574ff48d7639b255a36f9de6e7e9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "moxcms" -version = "0.7.8" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692af879e4d9383c0fd9dec15524af6b6977c8bf1c6b278a4526d5341347c574" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" dependencies = [ "num-traits", "pxfm", @@ -4634,20 +4855,11 @@ dependencies = [ "serde", ] -[[package]] -name = "nanoid" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" -dependencies = [ - "rand 0.8.5", -] - [[package]] name = "native-tls" -version = "0.2.14" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87de3442987e9dbec73158d5c715e7ad9072fda936bb03d19d7fa10e00520f0e" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" dependencies = [ "libc", "log", @@ -4655,63 +4867,68 @@ dependencies = [ "openssl-probe", "openssl-sys", "schannel", - "security-framework 2.11.1", + "security-framework", "security-framework-sys", "tempfile", ] [[package]] name = "ndarray" -version = "0.15.6" +version = "0.17.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adb12d4e967ec485a5f71c6311fe28158e9d6f4bc4a447b474184d0f91a8fa32" +checksum = "520080814a7a6b4a6e9070823bb24b4531daac8c4627e08ba5de8c5ef2f2752d" dependencies = [ - "approx 0.4.0", "matrixmultiply", "num-complex", "num-integer", "num-traits", + "portable-atomic", + "portable-atomic-util", "rawpointer", ] [[package]] name = "ndarray-stats" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af5a8477ac96877b5bd1fd67e0c28736c12943aba24eda92b127e036b0c8f400" +checksum = "9b6e54a8b65764f71827a90ca1d56965ec0c67f069f996477bd493402a901d1f" dependencies = [ - "indexmap 1.9.3", - "itertools 0.10.5", + "indexmap", + "itertools 0.13.0", "ndarray", "noisy_float", "num-integer", "num-traits", - "rand 0.8.5", + "rand 0.8.6", ] [[package]] name = "neli" -version = "0.6.5" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93062a0dce6da2517ea35f301dfc88184ce18d3601ec786a727a87bf535deca9" +checksum = "22f9786d56d972959e1408b6a93be6af13b9c1392036c5c1fafa08a1b0c6ee87" dependencies = [ + "bitflags", "byteorder", + "derive_builder", + "getset", "libc", "log", "neli-proc-macros", + "parking_lot", ] [[package]] name = "neli-proc-macros" -version = "0.1.4" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c8034b7fbb6f9455b2a96c19e6edf8dc9fc34c70449938d8ee3b4df363f61fe" +checksum = "05d8d08c6e98f20a62417478ebf7be8e1425ec9acecc6f63e22da633f6b71609" dependencies = [ "either", "proc-macro2", "quote", "serde", - "syn 1.0.109", + "syn 2.0.117", ] [[package]] @@ -4729,23 +4946,11 @@ dependencies = [ "smallvec", ] -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags 2.9.4", - "cfg-if", - "cfg_aliases", - "libc", -] - [[package]] name = "noisy_float" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978fe6e6ebc0bf53de533cd456ca2d9de13de13856eda1518a285d7705a213af" +checksum = "c16843be85dd410c6a12251c4eca0dd1d3ee8c5725f746c4d5e0fdcec0a864b2" dependencies = [ "num-traits", ] @@ -4762,34 +4967,20 @@ dependencies = [ [[package]] name = "ntapi" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +checksum = "c3b335231dfd352ffb0f8017f3b6027a4917f7df785ea2143d8af2adc66980ae" dependencies = [ "winapi", ] [[package]] name = "nu-ansi-term" -version = "0.50.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a28e057d01f97e61255210fcff094d74ed0466038633e95017f5beb68e4399" -dependencies = [ - "windows-sys 0.52.0", -] - -[[package]] -name = "num" -version = "0.4.3" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "num-bigint", - "num-complex", - "num-integer", - "num-iter", - "num-rational", - "num-traits", + "windows-sys 0.61.2", ] [[package]] @@ -4804,17 +4995,16 @@ dependencies = [ [[package]] name = "num-bigint-dig" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +checksum = "e661dda6640fad38e827a6d4a310ff4763082116fe217f279885c97f511bb0b7" dependencies = [ - "byteorder", "lazy_static", "libm", "num-integer", "num-iter", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "smallvec", "zeroize", ] @@ -4831,9 +5021,9 @@ dependencies = [ [[package]] name = "num-conv" -version = "0.1.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" [[package]] name = "num-integer" @@ -4855,17 +5045,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -4887,58 +5066,48 @@ dependencies = [ ] [[package]] -name = "num_enum" -version = "0.7.5" +name = "number_prefix" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" -dependencies = [ - "num_enum_derive", - "rustversion", -] +checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] -name = "num_enum_derive" -version = "0.7.5" +name = "objc2-core-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "proc-macro-crate", - "proc-macro2", - "quote", - "syn 2.0.106", + "bitflags", ] [[package]] -name = "number_prefix" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" - -[[package]] -name = "object" -version = "0.36.7" +name = "objc2-io-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" dependencies = [ - "memchr", + "libc", + "objc2-core-foundation", ] [[package]] name = "object_store" -version = "0.12.3" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efc4f07659e11cd45a341cd24d71e683e3be65d9ff1f8150061678fe60437496" +checksum = "622acbc9100d3c10e2ee15804b0caa40e55c933d5aa53814cd520805b7958a49" dependencies = [ "async-trait", "bytes", "chrono", - "futures", + "futures-channel", + "futures-core", + "futures-util", "http", "humantime", "itertools 0.14.0", "parking_lot", "percent-encoding", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tracing", "url", @@ -4989,25 +5158,34 @@ dependencies = [ "walkdir", ] +[[package]] +name = "oid-registry" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12f40cff3dde1b6087cc5d5f5d4d65712f34016a03ed60e9c08dcc392736b5b7" +dependencies = [ + "asn1-rs", +] + [[package]] name = "once_cell" -version = "1.21.3" +version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" [[package]] name = "once_cell_polyfill" -version = "1.70.1" +version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" +checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" [[package]] name = "onig" -version = "6.5.1" +version = "6.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b9c63443aceef14bea841b899035ae3abe89b7c486aaf4c5bd8aafedac3f0" +checksum = "0cc3cbf698f9438986c11a880c90a6d04b9de27575afd28bbf45b154b6c709e2" dependencies = [ - "bitflags 2.9.4", + "bitflags", "libc", "once_cell", "onig_sys", @@ -5015,9 +5193,9 @@ dependencies = [ [[package]] name = "onig_sys" -version = "69.9.1" +version = "69.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f86c6eef3d6df15f23bcfb6af487cbd2fed4e5581d58d5bf1f5f8b7f6727dc" +checksum = "1e68317604e77e53b85896388e1a803c1d21b74c899ec9e5e1112db90735edd7" dependencies = [ "cc", "pkg-config", @@ -5031,15 +5209,14 @@ checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl" -version = "0.10.73" +version = "0.10.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8" +checksum = "a45fa2aa886c42762255da344f0a0d313e254066c46aad76f300c3d3da62d967" dependencies = [ - "bitflags 2.9.4", + "bitflags", "cfg-if", "foreign-types", "libc", - "once_cell", "openssl-macros", "openssl-sys", ] @@ -5052,20 +5229,20 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "openssl-probe" -version = "0.1.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] name = "openssl-sys" -version = "0.9.109" +version = "0.9.116" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90096e2e47630d78b7d1c20952dc621f957103f8bc2c8359ec81290d75238571" +checksum = "f28a22dc7140cda5f096e5e7724a6962ca81a7f8bfd2979f9b18c11af56318c4" dependencies = [ "cc", "libc", @@ -5089,16 +5266,6 @@ dependencies = [ "hashbrown 0.14.5", ] -[[package]] -name = "owo-colors" -version = "4.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48dd4f4a2c8405440fd0462561f0e5806bd0f77e86f51c761481bdd4018b545e" -dependencies = [ - "supports-color 2.1.0", - "supports-color 3.0.2", -] - [[package]] name = "p256" version = "0.13.2" @@ -5123,6 +5290,16 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "papaya" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "997ee03cd38c01469a7046643714f0ad28880bcb9e6679ff0666e24817ca19b7" +dependencies = [ + "equivalent", + "seize", +] + [[package]] name = "parking" version = "2.2.1" @@ -5131,9 +5308,9 @@ checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] name = "parking_lot" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ "lock_api", "parking_lot_core", @@ -5141,15 +5318,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-targets 0.52.6", + "windows-link 0.2.1", ] [[package]] @@ -5199,14 +5376,20 @@ dependencies = [ "sha2 0.10.9", ] +[[package]] +name = "pdqselect" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec91767ecc0a0bbe558ce8c9da33c068066c57ecc8bb8477ef8c1ad3ef77c27" + [[package]] name = "pem" -version = "3.0.5" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38af38e8470ac9dee3ce1bae1af9c1671fffc44ddfd8bd1d0a3445bf349a8ef3" +checksum = "1d30c53c26bc5b31a98cd02d20f25a7c8567146caf63ed593a9d87b2775291be" dependencies = [ "base64 0.22.1", - "serde", + "serde_core", ] [[package]] @@ -5226,20 +5409,19 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.8.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1db05f56d34358a8b1066f67cbb203ee3e7ed2ba674a6263a1d5ec6db2204323" +checksum = "e0848c601009d37dfa3430c4666e147e49cdcf1b92ecd3e63657d8a5f19da662" dependencies = [ "memchr", - "thiserror 2.0.16", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.8.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb056d9e8ea77922845ec74a1c4e8fb17e7c218cc4fc11a15c5d25e189aa40bc" +checksum = "11f486f1ea21e6c10ed15d5a7c77165d0ee443402f0780849d1768e7d9d6fe77" dependencies = [ "pest", "pest_generator", @@ -5247,65 +5429,66 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.8.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e404e638f781eb3202dc82db6760c8ae8a1eeef7fb3fa8264b2ef280504966" +checksum = "8040c4647b13b210a963c1ed407c1ff4fdfa01c31d6d2a098218702e6664f94f" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "pest_meta" -version = "2.8.1" +version = "2.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd1101f170f5903fde0914f899bb503d9ff5271d7ba76bbb70bea63690cc0d5" +checksum = "89815c69d36021a140146f26659a81d6c2afa33d216d736dd4be5381a7362220" dependencies = [ "pest", "sha2 0.10.9", ] [[package]] -name = "petgraph" -version = "0.6.5" +name = "phf" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" dependencies = [ - "fixedbitset", - "indexmap 2.11.0", + "phf_macros 0.11.3", + "phf_shared 0.11.3", ] [[package]] -name = "pharos" -version = "0.5.3" +name = "phf" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9567389417feee6ce15dd6527a8a1ecac205ef62c2932bcf3d9f6fc5b78b414" +checksum = "c1562dc717473dbaa4c1f85a36410e03c047b2e7df7f45ee938fbef64ae7fadf" dependencies = [ - "futures", - "rustc_version", + "phf_macros 0.13.1", + "phf_shared 0.13.1", + "serde", ] [[package]] -name = "phf" +name = "phf_codegen" version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "phf_macros", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", ] [[package]] name = "phf_codegen" -version = "0.11.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +checksum = "49aa7f9d80421bca176ca8dbfebe668cc7a2684708594ec9f3c0db0805d5d6e1" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.13.1", + "phf_shared 0.13.1", ] [[package]] @@ -5314,8 +5497,18 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ - "phf_shared", - "rand 0.8.5", + "phf_shared 0.11.3", + "rand 0.8.6", +] + +[[package]] +name = "phf_generator" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "135ace3a761e564ec88c03a77317a7c6b80bb7f7135ef2544dbe054243b89737" +dependencies = [ + "fastrand", + "phf_shared 0.13.1", ] [[package]] @@ -5324,11 +5517,24 @@ version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f84ac04429c13a7ff43785d75ad27569f2951ce0ffd30a3321230db2fc727216" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "phf_macros" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "812f032b54b1e759ccd5f8b6677695d5268c588701effba24601f6932f8269ef" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "unicase", ] @@ -5339,40 +5545,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" dependencies = [ "siphasher", - "unicase", ] [[package]] -name = "pico-args" -version = "0.5.0" +name = "phf_shared" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be167a7af36ee22fe3115051bc51f6e6c7054c9348e28deb4f49bd6f705a315" +checksum = "e57fef6bc5981e38c2ce2d63bfa546861309f875b8a75f092d1d54ae2d64f266" +dependencies = [ + "siphasher", + "unicase", +] [[package]] name = "pin-project" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" +checksum = "2466b2336ed02bcdca6b294417127b90ec92038d1d5c4fbeac971a922e0e0924" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.10" +version = "1.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" +checksum = "c96395f0a926bc13b1c17622aaddda1ecb55d49c8f1bf9777e4d877800a43f8b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "pin-project-lite" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" [[package]] name = "pin-utils" @@ -5413,23 +5622,37 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.32" +version = "0.3.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +checksum = "19f132c84eca552bf34cab8ec81f1c1dcc229b811638f9d283dceabe58c5569e" [[package]] name = "png" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" dependencies = [ - "bitflags 2.9.4", + "bitflags", "crc32fast", "fdeflate", "flate2", "miniz_oxide", ] +[[package]] +name = "polling" +version = "3.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" +dependencies = [ + "cfg-if", + "concurrent-queue", + "hermit-abi", + "pin-project-lite", + "rustix", + "windows-sys 0.61.2", +] + [[package]] name = "polyval" version = "0.6.2" @@ -5437,22 +5660,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "opaque-debug", "universal-hash", ] [[package]] name = "portable-atomic" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" +checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49" + +[[package]] +name = "portable-atomic-util" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a106d1259c23fac8e543272398ae0e3c0b8d33c88ed73d0cc71b0f1d902618" +dependencies = [ + "portable-atomic", +] [[package]] name = "potential_utf" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84df19adbe5b5a0782edcab45899906947ab039ccf4573713735ee7de1e6b08a" +checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" dependencies = [ "zerovec", ] @@ -5478,6 +5710,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + [[package]] name = "primeorder" version = "0.13.6" @@ -5489,11 +5731,11 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35" +checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit", + "toml_edit 0.25.12+spec-1.1.0", ] [[package]] @@ -5515,14 +5757,14 @@ dependencies = [ "proc-macro-error-attr2", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "proc-macro2" -version = "1.0.101" +version = "1.0.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" dependencies = [ "unicode-ident", ] @@ -5535,11 +5777,23 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "version_check", "yansi", ] +[[package]] +name = "proc-macros" +version = "0.2.0" +dependencies = [ + "quote", + "salvo", + "serde", + "serde_json", + "surrealdb-types", + "syn 2.0.117", +] + [[package]] name = "prost" version = "0.10.4" @@ -5547,7 +5801,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71adf41db68aa0daaefc69bb30bcd68ded9b9abaad5d1fbb6304c4fb390e083e" dependencies = [ "bytes", - "prost-derive", + "prost-derive 0.10.1", +] + +[[package]] +name = "prost" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ea70524a2f82d518bce41317d0fae74151505651af45faf1ffbd6fd33f0568" +dependencies = [ + "bytes", + "prost-derive 0.14.3", ] [[package]] @@ -5563,6 +5827,19 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "prost-derive" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27c6023962132f4b30eb4c172c91ce92d933da334c59c23cddee82358ddafb0b" +dependencies = [ + "anyhow", + "itertools 0.14.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "prost-types" version = "0.10.1" @@ -5570,23 +5847,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d0a014229361011dc8e69c8a1ec6c2e8d0f2af7c91e3ea3f5b2170298461e68" dependencies = [ "bytes", - "prost", + "prost 0.10.4", ] [[package]] -name = "psl-types" -version = "2.0.11" +name = "prost-types" +version = "0.14.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" +checksum = "8991c4cbdb8bc5b11f0b074ffe286c30e523de90fee5ba8132f1399f23cb3dd7" +dependencies = [ + "prost 0.14.3", +] [[package]] -name = "psm" -version = "0.1.26" +name = "psl-types" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e944464ec8536cd1beb0bbfd96987eb5e3b72f2ecdafdc5c769a37f1fa2ae1f" -dependencies = [ - "cc", -] +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] name = "ptr_meta" @@ -5610,60 +5887,42 @@ dependencies = [ [[package]] name = "pulp" -version = "0.18.22" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a01a0dc67cf4558d279f0c25b0962bd08fc6dec0137699eae304103e882fe6" -dependencies = [ - "bytemuck", - "libm", - "num-complex", - "reborrow", -] - -[[package]] -name = "pulp" -version = "0.21.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b86df24f0a7ddd5e4b95c94fc9ed8a98f1ca94d3b01bdce2824097e7835907" +checksum = "2e205bb30d5b916c55e584c22201771bcf2bad9aabd5d4127f38387140c38632" dependencies = [ "bytemuck", "cfg-if", "libm", "num-complex", + "paste", + "pulp-wasm-simd-flag", + "raw-cpuid", "reborrow", "version_check", ] [[package]] -name = "pxfm" -version = "0.1.25" +name = "pulp-wasm-simd-flag" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3cbdf373972bf78df4d3b518d07003938e2c7d1fb5891e55f9cb6df57009d84" -dependencies = [ - "num-traits", -] +checksum = "40e24eee682d89fb193496edf918a7f407d30175b2e785fe057e4392dfd182e0" [[package]] -name = "quick_cache" -version = "0.5.2" +name = "pxfm" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb55a1aa7668676bb93926cd4e9cdfe60f03bb866553bcca9112554911b6d3dc" -dependencies = [ - "ahash 0.8.12", - "equivalent", - "hashbrown 0.14.5", - "parking_lot", -] +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" [[package]] name = "quick_cache" -version = "0.6.16" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ad6644cb07b7f3488b9f3d2fde3b4c0a7fa367cafefb39dff93a659f76eb786" +checksum = "d1c821816e9b928e20e92ed59bb3ac4aab321d16ca2316871c9fe7ca739cd477" dependencies = [ "ahash 0.8.12", "equivalent", - "hashbrown 0.15.5", + "hashbrown 0.16.1", "parking_lot", ] @@ -5675,13 +5934,14 @@ checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ "bytes", "cfg_aliases", + "futures-io", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash", "rustls", "socket2", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tracing", "web-time", @@ -5689,20 +5949,21 @@ dependencies = [ [[package]] name = "quinn-proto" -version = "0.11.13" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +checksum = "434b42fec591c96ef50e21e886936e66d3cc3f737104fdb9b737c40ffb94c098" dependencies = [ + "aws-lc-rs", "bytes", - "getrandom 0.3.3", + "getrandom 0.3.4", "lru-slab", - "rand 0.9.2", + "rand 0.9.4", "ring", "rustc-hash", "rustls", "rustls-pki-types", "slab", - "thiserror 2.0.16", + "thiserror 2.0.18", "tinyvec", "tracing", "web-time", @@ -5724,32 +5985,38 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.40" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924" dependencies = [ "proc-macro2", ] [[package]] name = "r-efi" -version = "5.3.0" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "r-efi" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "ractor" -version = "0.15.8" +version = "0.15.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a03628f080f90360ed29f8a577b90ad9488820e561d33d22f34f241e58845d" +checksum = "f12c86deb2af198b10a04c4fb3fba73baf3bb300df765a29272f0e5583da7510" dependencies = [ "async-trait", "bon", - "dashmap 6.1.0", + "dashmap", "futures", "js-sys", "once_cell", - "strum 0.26.3", + "strum 0.28.0", "tokio", "tokio_with_wasm", "tracing", @@ -5766,9 +6033,9 @@ checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" [[package]] name = "radix_trie" -version = "0.2.1" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c069c179fcdc6a2fe24d8d18305cf085fdbd4f922c041943e203685d6a1c58fd" +checksum = "3b4431027dcd37fc2a73ef740b5f233aa805897935b8bce0195e41bbf9a3289a" dependencies = [ "endian-type", "nibble_vec", @@ -5777,9 +6044,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +checksum = "5ca0ecfa931c29007047d1bc58e623ab12e5590e8c7cc53200d5202b69266d8a" dependencies = [ "libc", "rand_chacha 0.3.1", @@ -5788,12 +6055,23 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" dependencies = [ "rand_chacha 0.9.0", - "rand_core 0.9.3", + "rand_core 0.9.5", +] + +[[package]] +name = "rand" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207" +dependencies = [ + "chacha20", + "getrandom 0.4.2", + "rand_core 0.10.1", ] [[package]] @@ -5813,7 +6091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" dependencies = [ "ppv-lite86", - "rand_core 0.9.3", + "rand_core 0.9.5", ] [[package]] @@ -5822,18 +6100,24 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", ] [[package]] name = "rand_core" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" + [[package]] name = "rand_distr" version = "0.5.1" @@ -5841,16 +6125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8615d50dcf34fa31f7ab52692afec947c4dd0ab803cc87cb3b0b4570ff7463" dependencies = [ "num-traits", - "rand 0.9.2", -] - -[[package]] -name = "raw-cpuid" -version = "10.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" -dependencies = [ - "bitflags 1.3.2", + "rand 0.9.4", ] [[package]] @@ -5859,7 +6134,7 @@ version = "11.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" dependencies = [ - "bitflags 2.9.4", + "bitflags", ] [[package]] @@ -5870,9 +6145,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "rayon" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ "either", "rayon-core", @@ -5899,6 +6174,20 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "rcgen" +version = "0.14.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57f6d249aad744e274e682777a50283a225a32705394ee6d5fcc01efa25e4055" +dependencies = [ + "pem", + "ring", + "rustls-pki-types", + "time", + "x509-parser", + "yasna", +] + [[package]] name = "reblessive" version = "0.4.3" @@ -5913,11 +6202,11 @@ checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" [[package]] name = "redox_syscall" -version = "0.5.17" +version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.9.4", + "bitflags", ] [[package]] @@ -5926,7 +6215,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", "thiserror 1.0.69", ] @@ -5937,36 +6226,16 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" dependencies = [ - "getrandom 0.2.16", + "getrandom 0.2.17", "libredox", - "thiserror 2.0.16", -] - -[[package]] -name = "ref-cast" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf" -dependencies = [ - "ref-cast-impl", -] - -[[package]] -name = "ref-cast-impl" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "thiserror 2.0.18", ] [[package]] name = "regex" -version = "1.11.2" +version = "1.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" +checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276" dependencies = [ "aho-corasick", "memchr", @@ -5976,9 +6245,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.10" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" dependencies = [ "aho-corasick", "memchr", @@ -5986,16 +6255,16 @@ dependencies = [ ] [[package]] -name = "regex-lite" -version = "0.1.7" +name = "regex-syntax" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "943f41321c63ef1c92fd763bfe054d2668f7f225a5c29f0105903dc2fc04ba30" +checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] -name = "regex-syntax" -version = "0.8.6" +name = "relative-path" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" [[package]] name = "rend" @@ -6008,9 +6277,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.23" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d429f34c8092b2d42c7c93cec323bb4adeb7c67698f70839adec842ec10c7ceb" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", @@ -6028,12 +6297,9 @@ dependencies = [ "js-sys", "log", "mime", - "mime_guess", "native-tls", "percent-encoding", "pin-project-lite", - "quinn", - "rustls", "rustls-pki-types", "serde", "serde_json", @@ -6041,7 +6307,6 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", - "tokio-rustls", "tokio-util", "tower", "tower-http", @@ -6049,30 +6314,66 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.4.2", "web-sys", - "webpki-roots 1.0.2", ] [[package]] -name = "revision" -version = "0.10.0" +name = "reqwest" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22f53179a035f881adad8c4d58a2c599c6b4a8325b989c68d178d7a34d1b1e4c" +checksum = "219c5811de6525e5416c7d5d53bb656d3afdbc6c5af816e0802bcfa42dbdc1c3" dependencies = [ - "revision-derive 0.10.0", + "base64 0.22.1", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.5.0", + "web-sys", ] [[package]] name = "revision" -version = "0.11.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54b8ee532f15b2f0811eb1a50adf10d036e14a6cdae8d99893e7f3b921cb227d" +checksum = "3b66f44139d1fe8e1b6c21bf1a855f12df38517aab94e21cea2a077e9753f216" dependencies = [ + "bytes", "chrono", - "geo", + "geo 0.31.0", "regex", - "revision-derive 0.11.0", + "revision-derive", "roaring", "rust_decimal", "uuid", @@ -6080,24 +6381,13 @@ dependencies = [ [[package]] name = "revision-derive" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0ec466e5d8dca9965eb6871879677bef5590cf7525ad96cae14376efb75073" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", -] - -[[package]] -name = "revision-derive" -version = "0.11.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3415e1bc838c36f9a0a2ac60c0fa0851c72297685e66592c44870d82834dfa2" +checksum = "696cbf6f9d0bdeb7d75ef3a037c8295ea9fb665c89c6b70c23022f5918713353" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6118,17 +6408,17 @@ checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", "cfg-if", - "getrandom 0.2.16", + "getrandom 0.2.17", "libc", - "untrusted", + "untrusted 0.9.0", "windows-sys 0.52.0", ] [[package]] name = "rkyv" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +checksum = "2297bf9c81a3f0dc96bc9521370b88f054168c29826a75e89c55ff196e7ed6a1" dependencies = [ "bitvec", "bytecheck", @@ -6144,9 +6434,9 @@ dependencies = [ [[package]] name = "rkyv_derive" -version = "0.7.45" +version = "0.7.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +checksum = "84d7b42d4b8d06048d3ac8db0eb31bcb942cbeb709f0b5f2b2ebde398d3038f5" dependencies = [ "proc-macro2", "quote", @@ -6155,41 +6445,28 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" +checksum = "4ba8be72d372b2c9b35542551678538b562e7cf86c3315773cae48dfbfe7790c" dependencies = [ - "byteorder", "num-traits", - "paste", ] [[package]] name = "rmp-serde" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" +checksum = "72f81bee8c8ef9b577d1681a70ebbc962c232461e397b22c208c43c04b67a155" dependencies = [ - "byteorder", "rmp", "serde", ] -[[package]] -name = "rmpv" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58450723cd9ee93273ce44a20b6ec4efe17f8ed2e3631474387bfdecf18bb2a9" -dependencies = [ - "num-traits", - "rmp", -] - [[package]] name = "roaring" -version = "0.10.12" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e8d2cfa184d94d0726d650a9f4a1be7f9b76ac9fdb954219878dc00c1c1e7b" +checksum = "1dedc5658c6ecb3bdb5ef5f3295bb9253f42dcf3fd1402c03f6b1f7659c3c4a9" dependencies = [ "bytemuck", "byteorder", @@ -6204,21 +6481,23 @@ checksum = "4e27ee8bb91ca0adcf0ecb116293afa12d393f9c2b9b9cd54d33e8078fe19839" [[package]] name = "ron" -version = "0.8.1" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" +checksum = "4147b952f3f819eca0e99527022f7d6a8d05f111aeb0a62960c74eb283bec8fc" dependencies = [ - "base64 0.21.7", - "bitflags 2.9.4", + "bitflags", + "once_cell", "serde", "serde_derive", + "typeid", + "unicode-ident", ] [[package]] name = "rsa" -version = "0.9.8" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b" +checksum = "b8573f03f5883dcaebdfcf4725caa1ecb9c15b2ef50c43a07b816e06799bb12d" dependencies = [ "const-oid", "digest 0.10.7", @@ -6234,22 +6513,101 @@ dependencies = [ "zeroize", ] +[[package]] +name = "rstar" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a45c0e8804d37e4d97e55c6f258bc9ad9c5ee7b07437009dd152d764949a27c" +dependencies = [ + "heapless 0.6.1", + "num-traits", + "pdqselect", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b40f1bfe5acdab44bc63e6699c28b74f75ec43afb59f3eda01e145aff86a25fa" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f39465655a1e3d8ae79c6d9e007f4953bfc5d55297602df9dc38f9ae9f1359a" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + +[[package]] +name = "rstar" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73111312eb7a2287d229f06c00ff35b51ddee180f017ab6dec1f69d62ac098d6" +dependencies = [ + "heapless 0.7.17", + "num-traits", + "serde", + "smallvec", +] + [[package]] name = "rstar" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "421400d13ccfd26dfa5858199c30a5d76f9c54e0dba7575273025b43c5175dbb" dependencies = [ - "heapless", + "heapless 0.8.0", "num-traits", + "serde", "smallvec", ] +[[package]] +name = "rstest" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a3193c063baaa2a95a33f03035c8a72b83d97a54916055ba22d35ed3839d49" +dependencies = [ + "futures-timer", + "futures-util", + "rstest_macros", +] + +[[package]] +name = "rstest_macros" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c845311f0ff7951c5506121a9ad75aec44d083c31583b2ea5a30bcb0b0abba0" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn 2.0.117", + "unicode-ident", +] + [[package]] name = "rust-embed" -version = "8.7.2" +version = "8.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "025908b8682a26ba8d12f6f2d66b987584a4a87bc024abc5bbc12553a8cd178a" +checksum = "04113cb9355a377d83f06ef1f0a45b8ab8cd7d8b1288160717d66df5c7988d27" dependencies = [ "rust-embed-impl", "rust-embed-utils", @@ -6258,22 +6616,22 @@ dependencies = [ [[package]] name = "rust-embed-impl" -version = "8.7.2" +version = "8.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6065f1a4392b71819ec1ea1df1120673418bf386f50de1d6f54204d836d4349c" +checksum = "da0902e4c7c8e997159ab384e6d0fc91c221375f6894346ae107f47dd0f3ccaa" dependencies = [ "proc-macro2", "quote", "rust-embed-utils", - "syn 2.0.106", + "syn 2.0.117", "walkdir", ] [[package]] name = "rust-embed-utils" -version = "8.7.2" +version = "8.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6cc0c81648b20b70c491ff8cce00c1c3b223bb8ed2b5d41f0e54c6c4c0a3594" +checksum = "5bcdef0be6fe7f6fa333b1073c949729274b05f123a0ad7efcb8efd878e5c3b1" dependencies = [ "sha2 0.10.9", "walkdir", @@ -6301,69 +6659,65 @@ dependencies = [ [[package]] name = "rust_decimal" -version = "1.37.2" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d" +checksum = "0c5108e3d4d903e21aac27f12ba5377b6b34f9f44b325e4894c7924169d06995" dependencies = [ "arrayvec", "borsh", "bytes", "num-traits", - "rand 0.8.5", + "rand 0.8.6", "rkyv", "serde", "serde_json", + "wasm-bindgen", ] -[[package]] -name = "rustc-demangle" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" - [[package]] name = "rustc-hash" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" [[package]] -name = "rustc_lexer" -version = "0.1.0" +name = "rustc_version" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c86aae0c77166108c01305ee1a36a1e77289d7dc6ca0a3cd91ff4992de2d16a5" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ - "unicode-xid", + "semver", ] [[package]] -name = "rustc_version" -version = "0.4.1" +name = "rusticata-macros" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +checksum = "faf0c4a6ece9950b9abdb62b1cfcf2a68b3b67a10ba445b3bb85be2a293d0632" dependencies = [ - "semver", + "nom", ] [[package]] name = "rustix" -version = "1.0.8" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags 2.9.4", + "bitflags", "errno", "libc", "linux-raw-sys", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] name = "rustls" -version = "0.23.31" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0ebcbd2f03de0fc1122ad9bb24b127a5a6cd51d72604a3f3c50ac459762b6cc" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ + "aws-lc-rs", "log", "once_cell", "ring", @@ -6375,44 +6729,63 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" dependencies = [ "openssl-probe", "rustls-pki-types", "schannel", - "security-framework 3.4.0", + "security-framework", ] [[package]] -name = "rustls-pemfile" -version = "2.2.0" +name = "rustls-pki-types" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50" +checksum = "30a7197ae7eb376e574fe940d068c30fe0462554a3ddbe4eca7838e049c937a9" dependencies = [ - "rustls-pki-types", + "web-time", + "zeroize", ] [[package]] -name = "rustls-pki-types" -version = "1.12.0" +name = "rustls-platform-verifier" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "229a4a4c221013e7e1f1a043678c5cc39fe5171437c88fb47151a21e6f5b5c79" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ - "web-time", - "zeroize", + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", ] +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" -version = "0.103.4" +version = "0.103.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a17884ae0c1b773f1ccd2bd4a8c72f16da897310a98b0e84bf349ad5ead92fc" +checksum = "61c429a8649f110dddef65e2a5ad240f747e85f7758a6bccc7e5777bd33f756e" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", - "untrusted", + "untrusted 0.9.0", ] [[package]] @@ -6423,16 +6796,17 @@ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" [[package]] name = "ryu" -version = "1.0.20" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" +checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" [[package]] name = "safetensors" -version = "0.4.5" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44560c11236a6130a46ce36c836a62936dc81ebf8c36a37947423571be0e55b6" +checksum = "675656c1eabb620b921efea4f9199f97fc86e36dd6ffd1fbbe48d0f59a4987f5" dependencies = [ + "hashbrown 0.16.1", "serde", "serde_json", ] @@ -6448,11 +6822,11 @@ dependencies = [ [[package]] name = "salvo" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a0572f97daf740aec2898b4766e9572617ae2fba416a5f85de340b6e2a32ce9" +checksum = "997a9250e40b5c3122280212b03fa7579b548307a8239492eecc11d58da8a911" dependencies = [ - "salvo-jwt-auth", + "salvo-acme", "salvo-oapi", "salvo-proxy", "salvo-serve-static", @@ -6461,30 +6835,54 @@ dependencies = [ ] [[package]] -name = "salvo-jwt-auth" -version = "0.85.0" +name = "salvo-acme" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c2f4cb3b83ad27ac8f81684eb1f7dbc0fb339a44e292ca63fddb870e303c7a2" +checksum = "214d2a135ac07303211f70b64d8d5039b7886884cb811281d646ff0891e49767" dependencies = [ + "aws-lc-rs", "base64 0.22.1", "bytes", + "futures-util", + "http", "http-body-util", + "hyper", "hyper-rustls", "hyper-util", - "jsonwebtoken 10.1.0", + "parking_lot", + "quinn", + "rcgen", "salvo_core", "serde", "serde_json", - "thiserror 2.0.16", + "tokio", + "tokio-rustls", + "tracing", + "x509-parser", +] + +[[package]] +name = "salvo-http3" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b796803406733fab6a126e75bffb29f9e5336e8d42d39ea679ae381922059ed7" +dependencies = [ + "bytes", + "futures-util", + "h3", + "h3-datagram", + "h3-quinn", + "http", + "pin-project-lite", "tokio", "tracing", ] [[package]] name = "salvo-oapi" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c70018652cde7655703cb6c4db4715c59469527e06c07c48fa80be8e865dd5" +checksum = "e639ba263b1fafa79309c2262cca93612f6777c3559f7a121f367a1c3f36605b" dependencies = [ "anyhow", "base64 0.22.1", @@ -6493,7 +6891,7 @@ dependencies = [ "compact_str", "futures-util", "http", - "indexmap 2.11.0", + "indexmap", "inventory", "mime-infer", "parking_lot", @@ -6506,7 +6904,7 @@ dependencies = [ "serde_json", "serde_norway", "smallvec", - "thiserror 2.0.16", + "thiserror 2.0.18", "time", "tokio", "tracing", @@ -6517,9 +6915,9 @@ dependencies = [ [[package]] name = "salvo-oapi-macros" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb4fd14a5b451acad2bfe5de53fa8ebd1c85ec416490d0ab633883324be64ee7" +checksum = "6f8cfa5ba6f6ad5ce247cfe05a6570858f0967ef83aabf984f8c3ed7f6fa7ad3" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -6527,14 +6925,14 @@ dependencies = [ "quote", "regex", "salvo-serde-util", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "salvo-proxy" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3032a022ccf9d50fd420412dc265c7729f65f30646650a17eb61a8d5575b880" +checksum = "1501355e3361174931a91cd8c4026061ffdebb1757aa2ed449d97d33a178ee92" dependencies = [ "fastrand", "futures-util", @@ -6543,7 +6941,7 @@ dependencies = [ "hyper-util", "local-ip-address", "percent-encoding", - "reqwest", + "reqwest 0.13.4", "salvo_core", "tokio", "tracing", @@ -6551,20 +6949,20 @@ dependencies = [ [[package]] name = "salvo-serde-util" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb7587e297e6b75aee58de7b2d5a24f7378f1ac50a3bf9739fa88821d146f04c" +checksum = "c513cc94967322fab6ac2f1b3e68d40e110971fd4924f4d48677ca6e7df41038" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "salvo-serve-static" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c31a971fc487cf728e589f08996bab0153647bad3e49d35fec5df7c6796611e6" +checksum = "a294628f2bc06d5152a61cdcf086fbab2194b16c1e40b158e6a1ba2b520c90ba" dependencies = [ "hex", "mime", @@ -6582,9 +6980,9 @@ dependencies = [ [[package]] name = "salvo_core" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4f710aaf46666f08b3cc4b8ad761e3a00d381a2abe7e2d6448d0f594be72ab7" +checksum = "a6b94eccfe18383d4db6dbc6a0462f1be4160467e8d42506db8e46932b8fd5a3" dependencies = [ "async-trait", "base64 0.22.1", @@ -6599,24 +6997,24 @@ dependencies = [ "form_urlencoded", "futures-channel", "futures-util", + "h3-datagram", "headers", "http", "http-body-util", "hyper", - "hyper-rustls", "hyper-util", - "indexmap 2.11.0", + "indexmap", "mime", "mime-infer", "multer", "multimap", - "nix", "parking_lot", "percent-encoding", "pin-project", - "rand 0.9.2", + "quinn", + "rand 0.10.1", "regex", - "rustls-pemfile", + "salvo-http3", "salvo_macros", "serde", "serde-xml-rs", @@ -6624,7 +7022,7 @@ dependencies = [ "serde_urlencoded", "sync_wrapper", "tempfile", - "thiserror 2.0.16", + "thiserror 2.0.18", "tokio", "tokio-rustls", "tokio-util", @@ -6635,9 +7033,9 @@ dependencies = [ [[package]] name = "salvo_extra" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7380e3bc5f24ad9529e929fd391715ae3def92feefc9fece038f14a2e3b86ec3" +checksum = "e4929b192e8563f228f4f0686b3bf33a33752cfc8e5b03ed409859504c4b2ce2" dependencies = [ "base64 0.22.1", "etag", @@ -6649,7 +7047,7 @@ dependencies = [ "serde", "serde_json", "tokio", - "tokio-tungstenite 0.28.0", + "tokio-tungstenite 0.29.0", "tower", "tracing", "ulid", @@ -6657,16 +7055,16 @@ dependencies = [ [[package]] name = "salvo_macros" -version = "0.85.0" +version = "0.89.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8191db21784912e4a08e800005761e3f25412e08dd9fd20a1a6ff22270afa8bd" +checksum = "a51d5f03526f7cc1cc38b60cc24c3cc5982516c8ad9c94ff27d7f82f3c9762fb" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", "regex", "salvo-serde-util", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6680,42 +7078,43 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.27" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] -name = "schemars" -version = "0.9.0" +name = "scopeguard" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" -dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", -] +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "schemars" -version = "1.0.4" +name = "scraper" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d20c4491bc164fa2f6c5d44565947a52ad80b9505d8e36f8d54c27c739fcd0" +checksum = "93cecd86d6259499c844440546d02f55f3e17bd286e529e48d1f9f67e92315cb" dependencies = [ - "dyn-clone", - "ref-cast", - "serde", - "serde_json", + "cssparser 0.36.0", + "ego-tree", + "getopts", + "html5ever 0.36.1", + "precomputed-hash", + "selectors", + "tendril", ] [[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +name = "scratch" +version = "0.2.0" +dependencies = [ + "macros", + "proc-macros", + "serde", + "surrealdb-types", +] [[package]] name = "scrypt" @@ -6743,7 +7142,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" dependencies = [ "base16ct", "der 0.7.10", - "generic-array", + "generic-array 0.14.9", "pkcs8 0.10.2", "serdect", "subtle", @@ -6752,54 +7151,65 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.11.1" +version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.9.4", + "bitflags", + "core-foundation 0.10.1", "core-foundation-sys", "libc", "security-framework-sys", ] [[package]] -name = "security-framework" -version = "3.4.0" +name = "security-framework-sys" +version = "2.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60b369d18893388b345804dc0007963c99b7d665ae71d275812d828c6f089640" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" dependencies = [ - "bitflags 2.9.4", - "core-foundation 0.10.1", "core-foundation-sys", "libc", - "security-framework-sys", ] [[package]] -name = "security-framework-sys" -version = "2.15.0" +name = "seize" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc1f0cbffaac4852523ce30d8bd3c5cdc873501d96ff467ca09b6767bb8cd5c0" +checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521" dependencies = [ - "core-foundation-sys", "libc", + "windows-sys 0.61.2", ] [[package]] -name = "semver" -version = "1.0.26" +name = "selectors" +version = "0.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56e6fa9c48d24d85fb3de5ad847117517440f6beceb7798af16b4a87d616b8d0" +checksum = "feef350c36147532e1b79ea5c1f3791373e61cbd9a6a2615413b3807bb164fb7" dependencies = [ - "serde", + "bitflags", + "cssparser 0.36.0", + "derive_more", + "log", + "new_debug_unreachable", + "phf 0.13.1", + "phf_codegen 0.13.1", + "precomputed-hash", + "rustc-hash", + "servo_arc", + "smallvec", ] [[package]] -name = "send_wrapper" -version = "0.6.0" +name = "semver" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" +dependencies = [ + "serde", + "serde_core", +] [[package]] name = "seq-macro" @@ -6836,12 +7246,13 @@ dependencies = [ [[package]] name = "serde-untagged" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34836a629bcbc6f1afdf0907a744870039b1e14c0561cb26094fa683b158eff3" +checksum = "f9faf48a4a2d2693be24c6289dbe26552776eb7737074e6722891fadbe6c5058" dependencies = [ "erased-serde", "serde", + "serde_core", "typeid", ] @@ -6858,14 +7269,14 @@ dependencies = [ [[package]] name = "serde-xml-rs" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53630160a98edebde0123eb4dfd0fce6adff091b2305db3154a9e920206eb510" +checksum = "cc2215ce3e6a77550b80a1c37251b7d294febaf42e36e21b7b411e0bf54d540d" dependencies = [ "log", "serde", - "thiserror 1.0.69", - "xml-rs", + "thiserror 2.0.18", + "xml", ] [[package]] @@ -6885,20 +7296,20 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "serde_json" -version = "1.0.143" +version = "1.0.150" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" dependencies = [ - "indexmap 2.11.0", "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -6907,7 +7318,7 @@ version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e408f29489b5fd500fab51ff1484fc859bb655f32c671f307dcd733b72e8168c" dependencies = [ - "indexmap 2.11.0", + "indexmap", "itoa", "ryu", "serde", @@ -6931,7 +7342,7 @@ checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -6945,11 +7356,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -6965,45 +7376,22 @@ dependencies = [ ] [[package]] -name = "serde_with" -version = "3.14.0" +name = "serdect" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2c45cd61fefa9db6f254525d46e392b852e0e61d9a1fd36e5bd183450a556d5" +checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" dependencies = [ - "base64 0.22.1", - "chrono", - "hex", - "indexmap 1.9.3", - "indexmap 2.11.0", - "schemars 0.9.0", - "schemars 1.0.4", + "base16ct", "serde", - "serde_derive", - "serde_json", - "serde_with_macros", - "time", -] - -[[package]] -name = "serde_with_macros" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de90945e6565ce0d9a25098082ed4ee4002e047cb59892c318d66821e14bb30f" -dependencies = [ - "darling", - "proc-macro2", - "quote", - "syn 2.0.106", ] [[package]] -name = "serdect" -version = "0.2.0" +name = "servo_arc" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a84f14a19e9a014bb9f4512488d9829a68e04ecabffb0f9904cd1ace94598177" +checksum = "170fb83ab34de17dc69aa7c67482b22218ddb85da56546f9bd6b929e32a05930" dependencies = [ - "base16ct", - "serde", + "stable_deref_trait", ] [[package]] @@ -7013,7 +7401,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -7025,7 +7413,7 @@ checksum = "4d58a1e1bf39749807d89cf2d98ac2dfa0ff1cb3faa38fbb64dd88ac8013d800" dependencies = [ "block-buffer 0.9.0", "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.9.0", "opaque-debug", ] @@ -7037,7 +7425,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest 0.10.7", ] @@ -7056,12 +7444,25 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "sif-itree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7f45b8998ced5134fb1d75732c77842a3e888f19c1ff98481822e8fbfbf930b" + [[package]] name = "signal-hook-registry" -version = "1.4.6" +version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" dependencies = [ + "errno", "libc", ] @@ -7077,9 +7478,19 @@ dependencies = [ [[package]] name = "simd-adler32" -version = "0.3.7" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_cesu8" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] [[package]] name = "simdutf8" @@ -7089,78 +7500,66 @@ checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "simple_asn1" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297f631f50729c8c99b84667867963997ec0b50f32b2a7dbcab828ef0541e8bb" +checksum = "0d585997b0ac10be3c5ee635f1bab02d512760d14b7c468801ac8a01d9ae5f1d" dependencies = [ "num-bigint", "num-traits", - "thiserror 2.0.16", + "thiserror 2.0.18", "time", ] [[package]] name = "siphasher" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" [[package]] name = "slab" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" - -[[package]] -name = "smol_str" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] [[package]] name = "snafu" -version = "0.8.9" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e84b3f4eacbf3a1ce05eac6763b4d629d60cbc94d632e4092c54ade71f1e1a2" +checksum = "d1a012328be2e3f5d5f6f3218147ca02588cea4cb865e876849ab6debcf36522" dependencies = [ "snafu-derive", ] [[package]] name = "snafu-derive" -version = "0.8.9" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c97747dbf44bb1ca44a561ece23508e99cb592e862f22222dcf42f51d1e451" +checksum = "5f103c50866b8743da9429b8a581d81a27c2d3a9c4ac7df8f8571c1dd7896eda" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] -[[package]] -name = "snap" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6b67fb9a61334225b5b790716f609cd58395f895b3fe8b328786812a40bc3b" - [[package]] name = "socket2" -version = "0.6.0" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807" +checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" dependencies = [ "libc", - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] @@ -7176,11 +7575,11 @@ dependencies = [ [[package]] name = "spade" -version = "2.15.0" +version = "2.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb313e1c8afee5b5647e00ee0fe6855e3d529eb863a0fdae1d60006c4d1e9990" +checksum = "9699399fd9349b00b184f5635b074f9ec93afffef30c853f8c875b32c0f8c7fa" dependencies = [ - "hashbrown 0.15.5", + "hashbrown 0.16.1", "num-traits", "robust", "smallvec", @@ -7191,6 +7590,9 @@ name = "spin" version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" +dependencies = [ + "lock_api", +] [[package]] name = "spki" @@ -7225,22 +7627,9 @@ dependencies = [ [[package]] name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "stacker" -version = "0.1.21" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cddb07e32ddb770749da91081d8d0ac3a16f1a569a18b20348cd371f5dead06b" -dependencies = [ - "cc", - "cfg-if", - "libc", - "psm", - "windows-sys 0.59.0", -] +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] name = "static_assertions" @@ -7256,14 +7645,24 @@ checksum = "d7beae5182595e9a8b683fa98c4317f956c9a2dec3b9716990d20023cc60c766" [[package]] name = "storekey" -version = "0.5.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c42833834a5d23b344f71d87114e0cc9994766a5c42938f4b50e7b2aef85b2" +checksum = "bd9a94571bde7369ecaac47cec2e6844642d99166bd452fbd8def74b5b917b2f" dependencies = [ - "byteorder", - "memchr", - "serde", - "thiserror 1.0.69", + "bytes", + "storekey-derive", + "uuid", +] + +[[package]] +name = "storekey-derive" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6079d53242246522ec982de613c5c952cc7b1380ef2f8622fcdab9bfe73c0098" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] @@ -7274,9 +7673,9 @@ checksum = "0ceb97b7225c713c2fd4db0153cb6b3cab244eb37900c3f634ed4d43310d8c34" [[package]] name = "str-macro" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7514866270741c7b03dd36e2c68f71cf064b230e8217c81bbd4d619d564864" +checksum = "478f911a08456fce4457f68af0974c513895f07ff51f3417242fb99efb4c909a" [[package]] name = "string_cache" @@ -7286,19 +7685,43 @@ checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", "parking_lot", - "phf_shared", + "phf_shared 0.11.3", "precomputed-hash", "serde", ] +[[package]] +name = "string_cache" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a18596f8c785a729f2819c0f6a7eae6ebeebdfffbfe4214ae6b087f690e31901" +dependencies = [ + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.13.1", + "precomputed-hash", +] + [[package]] name = "string_cache_codegen" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" dependencies = [ - "phf_generator", - "phf_shared", + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] + +[[package]] +name = "string_cache_codegen" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585635e46db231059f76c5849798146164652513eb9e8ab2685939dd90f29b69" +dependencies = [ + "phf_generator 0.13.1", + "phf_shared 0.13.1", "proc-macro2", "quote", ] @@ -7314,15 +7737,24 @@ name = "strum" version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros 0.26.4", -] [[package]] name = "strum" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" +dependencies = [ + "strum_macros 0.27.2", +] + +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros 0.28.0", +] [[package]] name = "strum_macros" @@ -7330,11 +7762,11 @@ version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", "rustversion", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7343,179 +7775,163 @@ version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] -name = "subtle" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" - -[[package]] -name = "supports-color" -version = "2.1.0" +name = "strum_macros" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" dependencies = [ - "is-terminal", - "is_ci", + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "supports-color" -version = "3.0.2" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6" -dependencies = [ - "is_ci", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "surrealdb" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4636ac0af4dd619a66d55d8b5c0d1a0965ac1fe417c6a39dbc1d3db16588b969" +version = "3.1.3" dependencies = [ - "arrayvec", + "anyhow", "async-channel", - "bincode", + "boxcar", "chrono", - "dmp", "futures", - "geo", - "getrandom 0.3.3", - "indexmap 2.11.0", + "getrandom 0.3.4", + "indexmap", + "js-sys", "path-clean", - "pharos", - "reblessive", - "reqwest", - "revision 0.11.0", + "reqwest 0.13.4", "ring", - "rust_decimal", "rustls", "rustls-pki-types", "semver", "serde", - "serde-content", "serde_json", "surrealdb-core", - "thiserror 1.0.69", + "surrealdb-types", + "surrealdb-types-derive", "tokio", - "tokio-tungstenite 0.23.1", + "tokio-tungstenite 0.28.0", + "tokio-tungstenite-wasm", "tokio-util", "tracing", - "trice", "url", "uuid", + "wasm-bindgen", "wasm-bindgen-futures", "wasmtimer", - "ws_stream_wasm", + "web-sys", ] [[package]] name = "surrealdb-core" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b99720b7f5119785b065d235705ca95f568a9a89745d1221871e845eedf424d" +version = "3.1.3" dependencies = [ "addr", "affinitypool", "ahash 0.8.12", "ammonia", - "any_ascii", + "anyhow", "argon2", "async-channel", - "async-executor", "async-graphql", - "base64 0.21.7", + "async-stream", + "async-trait", + "base64 0.22.1", "bcrypt", - "bincode", "blake3", "bytes", - "castaway", - "cedar-policy", "chrono", "ciborium", - "dashmap 5.5.3", + "dashmap", "deunicode", "dmp", "ext-sort", + "fastnum", "fst", "futures", "fuzzy-matcher", - "geo", + "geo 0.32.0", "geo-types", - "getrandom 0.3.3", + "getrandom 0.3.4", + "headers", "hex", "http", + "humantime", "ipnet", - "jsonwebtoken 9.3.1", - "lexicmp 0.1.0", - "linfa-linalg", + "jsonwebtoken", + "lexicmp", "md-5", - "nanoid", + "mimalloc", + "mime", "ndarray", "ndarray-stats", "num-traits", "num_cpus", "object_store", "parking_lot", + "path-clean", "pbkdf2", - "pharos", - "phf", + "phf 0.13.1", "pin-project-lite", - "quick_cache 0.5.2", + "quick_cache", "radix_trie", - "rand 0.8.5", + "rand 0.8.6", "rayon", "reblessive", "regex", - "reqwest", - "revision 0.11.0", + "revision", "ring", - "rmpv", "roaring", "rust-stemmers", "rust_decimal", "scrypt", "semver", "serde", - "serde-content", "serde_json", "sha1", "sha2 0.10.9", - "snap", "storekey", "strsim", "subtle", + "surrealdb-protocol", "surrealdb-rocksdb", - "surrealkv", + "surrealdb-types", + "surrealmx", "sysinfo", "tempfile", - "thiserror 1.0.69", + "thiserror 2.0.18", "tikv-jemallocator", "tokio", + "tokio-util", "tracing", - "trice", "ulid", "unicase", "url", "uuid", - "vart 0.8.1", + "vart", "wasm-bindgen-futures", "wasmtimer", - "ws_stream_wasm", + "web-time", ] [[package]] name = "surrealdb-librocksdb-sys" -version = "0.17.3+10.6.2" +version = "0.18.3+11.0.0-4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db194f1cf601bb6f2d0f4cbf0931bc3e5a602bac41ef2e9a87eccdfb28b7fed2" +checksum = "25b82a18c7fa4b57206784a1a31e7b942ae1d3e24493e0c733019a409b2b4bea" dependencies = [ "bindgen", "bzip2-sys", @@ -7527,59 +7943,99 @@ dependencies = [ ] [[package]] -name = "surrealdb-migrations" -version = "2.3.0" -source = "git+https://github.com/disconsented/surrealdb-migrations.git#e8c9a439310d163da6dc7f655661250d9e491f9f" +name = "surrealdb-protocol" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f4e06f586c9179a02349b88b0c18e3a0850c55431aa513e0cd66529c00da1af" dependencies = [ + "anyhow", + "async-trait", + "bytes", "chrono", - "chrono-human-duration", - "clap", - "cli-table", - "color-eyre", - "diffy", - "fs_extra", + "flatbuffers", "futures", - "hex", - "include_dir", - "itertools 0.14.0", - "lexicmp 0.2.0", - "owo-colors", - "regex-lite", - "rust-ini", + "geo 0.32.0", + "prost 0.14.3", + "prost-types 0.14.3", + "rust_decimal", + "semver", "serde", "serde_json", - "sha2 0.10.9", - "surrealdb", - "tokio", + "tonic", + "tonic-prost", + "uuid", ] [[package]] name = "surrealdb-rocksdb" -version = "0.24.0-surreal.1" +version = "0.24.0-surreal.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057727f56d48825ddbe45e4e7401cda6e99d864fbc004e7474b4689a5e72c86d" +checksum = "02e8c3a004982458af159bcbf369e41663d538cd4a291a49c0d4a2fb373cbb7e" dependencies = [ "libc", "surrealdb-librocksdb-sys", ] [[package]] -name = "surrealkv" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a5041979bdff8599a1d5f6cb7365acb9a79664e2a84e5c4fddac2b3969f7d1" +name = "surrealdb-types" +version = "3.1.3" dependencies = [ - "ahash 0.8.12", + "anyhow", + "async-channel", "bytes", + "castaway", "chrono", - "crc32fast", - "double-ended-peekable", - "getrandom 0.2.16", - "lru", + "flatbuffers", + "geo 0.32.0", + "hex", + "http", + "papaya", + "rand 0.8.6", + "regex", + "reqwest 0.13.4", + "rstest", + "rust_decimal", + "semver", + "serde", + "serde_json", + "surrealdb-protocol", + "surrealdb-types-derive", + "tracing", + "ulid", + "url", + "uuid", +] + +[[package]] +name = "surrealdb-types-derive" +version = "3.1.3" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "surrealmx" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6508449a7d1379a92a51ba49391b48ccab0b60dd11a4277c0dda965d8c99dbff" +dependencies = [ + "arc-swap", + "bincode", + "bytes", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-skiplist", + "lz4", + "papaya", "parking_lot", - "quick_cache 0.6.16", - "revision 0.10.0", - "vart 0.9.3", + "serde", + "smallvec", + "thiserror 2.0.18", + "tracing", + "web-time", ] [[package]] @@ -7595,9 +8051,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.106" +version = "2.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6" +checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99" dependencies = [ "proc-macro2", "quote", @@ -7621,21 +8077,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", -] - -[[package]] -name = "sysctl" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea" -dependencies = [ - "bitflags 2.9.4", - "byteorder", - "enum-as-inner", - "libc", - "thiserror 1.0.69", - "walkdir", + "syn 2.0.117", ] [[package]] @@ -7644,7 +8086,7 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01198a2debb237c62b6826ec7081082d951f46dbb64b0e8c7649a452230d1dfc" dependencies = [ - "bitflags 2.9.4", + "bitflags", "byteorder", "enum-as-inner", "libc", @@ -7654,25 +8096,25 @@ dependencies = [ [[package]] name = "sysinfo" -version = "0.33.1" +version = "0.37.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc858248ea01b66f19d8e8a6d55f41deaf91e9d495246fd01368d99935c6c01" +checksum = "16607d5caffd1c07ce073528f9ed972d88db15dd44023fa57142963be3feb11f" dependencies = [ - "core-foundation-sys", "libc", "memchr", "ntapi", - "rayon", + "objc2-core-foundation", + "objc2-io-kit", "windows", ] [[package]] name = "system-configuration" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" +checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.9.4", + "bitflags", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -7695,9 +8137,9 @@ checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "tar" -version = "0.4.44" +version = "0.4.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d863878d212c87a19c1a610eb53bb01fe12951c0501cf5a0d65f724914a667a" +checksum = "3f6221d9a6003c78398e3b239969f352578258df48c8eb051caadae0015bc840" dependencies = [ "filetime", "libc", @@ -7706,15 +8148,15 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.21.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b61f8f20e3a6f7e0649d825294eaf317edce30f82cf6026e7e4cb9222a7d1e" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.3.3", + "getrandom 0.4.2", "once_cell", "rustix", - "windows-sys 0.60.2", + "windows-sys 0.61.2", ] [[package]] @@ -7728,26 +8170,6 @@ dependencies = [ "utf-8", ] -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", -] - [[package]] name = "thiserror" version = "1.0.69" @@ -7759,11 +8181,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" dependencies = [ - "thiserror-impl 2.0.16", + "thiserror-impl 2.0.18", ] [[package]] @@ -7774,18 +8196,18 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "thiserror-impl" -version = "2.0.16" +version = "2.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7799,9 +8221,9 @@ dependencies = [ [[package]] name = "tikv-jemalloc-sys" -version = "0.6.0+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" +version = "0.6.1+5.3.0-1-ge13ca993e8ccb9ba9847cc330696e02839f328f7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3c60906412afa9c2b5b5a48ca6a5abe5736aec9eb48ad05037a677e52e4e2d" +checksum = "cd8aa5b2ab86a2cefa406d889139c162cbb230092f7d1d7cbc1716405d852a3b" dependencies = [ "cc", "libc", @@ -7809,9 +8231,9 @@ dependencies = [ [[package]] name = "tikv-jemallocator" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cec5ff18518d81584f477e9bfdf957f5bb0979b0bac3af4ca30b5b3ae2d2865" +checksum = "0359b4327f954e0567e69fb191cf1436617748813819c94b8cd4a431422d053a" dependencies = [ "libc", "tikv-jemalloc-sys", @@ -7819,29 +8241,30 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" dependencies = [ "deranged", + "itoa", "num-conv", "powerfmt", - "serde", + "serde_core", "time-core", "time-macros", ] [[package]] name = "time-core" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" [[package]] name = "time-macros" -version = "0.2.24" +version = "0.2.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" dependencies = [ "num-conv", "time-core", @@ -7858,9 +8281,9 @@ dependencies = [ [[package]] name = "tinystr" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b" +checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" dependencies = [ "displaydoc", "zerovec", @@ -7868,9 +8291,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.10.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" dependencies = [ "tinyvec_macros", ] @@ -7883,9 +8306,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokenizers" -version = "0.21.4" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a620b996116a59e184c2fa2dfd8251ea34a36d0a514758c6f966386bd2e03476" +checksum = "b238e22d44a15349529690fb07bd645cf58149a1b1e44d6cb5bd1641ff1a6223" dependencies = [ "ahash 0.8.12", "aho-corasick", @@ -7893,15 +8316,15 @@ dependencies = [ "dary_heap", "derive_builder", "esaxx-rs", - "getrandom 0.3.3", - "indicatif", + "getrandom 0.3.4", + "indicatif 0.18.4", "itertools 0.14.0", "log", "macro_rules_attribute", "monostate", "onig", "paste", - "rand 0.9.2", + "rand 0.9.4", "rayon", "rayon-cond", "regex", @@ -7909,7 +8332,7 @@ dependencies = [ "serde", "serde_json", "spm_precompiled", - "thiserror 2.0.16", + "thiserror 2.0.18", "unicode-normalization-alignments", "unicode-segmentation", "unicode_categories", @@ -7917,9 +8340,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.48.0" +version = "1.52.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" +checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" dependencies = [ "bytes", "libc", @@ -7930,18 +8353,18 @@ dependencies = [ "socket2", "tokio-macros", "tracing", - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] name = "tokio-macros" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -7956,19 +8379,30 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" dependencies = [ "rustls", "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-tungstenite" -version = "0.23.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" dependencies = [ "futures-util", "log", @@ -7976,27 +8410,46 @@ dependencies = [ "rustls-pki-types", "tokio", "tokio-rustls", - "tungstenite 0.23.0", + "tungstenite 0.28.0", "webpki-roots 0.26.11", ] [[package]] name = "tokio-tungstenite" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +checksum = "8f72a05e828585856dacd553fba484c242c46e391fb0e58917c942ee9202915c" dependencies = [ "futures-util", "log", "tokio", - "tungstenite 0.28.0", + "tungstenite 0.29.0", +] + +[[package]] +name = "tokio-tungstenite-wasm" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccecee909c02b8863f9bda87253127eb4da0e7e1342330b2583fbc4d1795c2f8" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "httparse", + "js-sys", + "thiserror 2.0.18", + "tokio", + "tokio-tungstenite 0.28.0", + "wasm-bindgen", + "web-sys", ] [[package]] name = "tokio-util" -version = "0.7.16" +version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5" +checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", @@ -8008,9 +8461,9 @@ dependencies = [ [[package]] name = "tokio_with_wasm" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dfba9b946459940fb564dcf576631074cdfb0bfe4c962acd4c31f0dca7897e6" +checksum = "34e40fbbbd95441133fe9483f522db15dbfd26dc636164ebd8f2dd28759a6aa6" dependencies = [ "js-sys", "tokio", @@ -8022,12 +8475,12 @@ dependencies = [ [[package]] name = "tokio_with_wasm_proc" -version = "0.8.7" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e04c1865c281139e5ccf633cb9f76ffdaabeebfe53b703984cf82878e2aabb" +checksum = "d01145a2c788d6aae4cd653afec1e8332534d7d783d01897cefcafe4428de992" dependencies = [ "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -8039,20 +8492,20 @@ dependencies = [ "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", - "toml_edit", + "toml_edit 0.22.27", ] [[package]] name = "toml" -version = "0.9.5" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "81f3d15e84cbcd896376e6730314d59fb5a87f31e4b038454184435cd57defee" dependencies = [ - "serde", - "serde_spanned 1.0.0", - "toml_datetime 0.7.0", + "serde_core", + "serde_spanned 1.1.1", + "toml_datetime 1.1.1+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.3", ] [[package]] @@ -8066,11 +8519,11 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -8079,21 +8532,33 @@ version = "0.22.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a" dependencies = [ - "indexmap 2.11.0", + "indexmap", "serde", "serde_spanned 0.6.9", "toml_datetime 0.6.11", "toml_write", - "winnow", + "winnow 0.7.15", +] + +[[package]] +name = "toml_edit" +version = "0.25.12+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2153edc6955a6c354fad8f5efd38b6a8769bdccf9fe50f8e1329f81b0baa5d7" +dependencies = [ + "indexmap", + "toml_datetime 1.1.1+spec-1.1.0", + "toml_parser", + "winnow 1.0.3", ] [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "a2abe9b86193656635d2411dc43050282ca48aa31c2451210f4202550afb7526" dependencies = [ - "winnow", + "winnow 1.0.3", ] [[package]] @@ -8102,15 +8567,57 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801" +[[package]] +name = "tonic" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac2a5518c70fa84342385732db33fb3f44bc4cc748936eb5833d2df34d6445ef" +dependencies = [ + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-timeout", + "hyper-util", + "percent-encoding", + "pin-project", + "socket2", + "sync_wrapper", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tonic-prost" +version = "0.14.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50849f68853be452acf590cde0b146665b8d507b3b8af17261df47e02c209ea0" +dependencies = [ + "bytes", + "prost 0.14.3", + "tonic", +] + [[package]] name = "tower" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" dependencies = [ "futures-core", "futures-util", + "indexmap", "pin-project-lite", + "slab", "sync_wrapper", "tokio", "tokio-util", @@ -8121,20 +8628,20 @@ dependencies = [ [[package]] name = "tower-http" -version = "0.6.6" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.9.4", + "bitflags", "bytes", "futures-util", "http", "http-body", - "iri-string", "pin-project-lite", "tower", "tower-layer", "tower-service", + "url", ] [[package]] @@ -8151,9 +8658,9 @@ checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[package]] name = "tracing" -version = "0.1.41" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -8162,35 +8669,25 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "tracing-core" -version = "0.1.34" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", ] -[[package]] -name = "tracing-error" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b1581020d7a273442f5b45074a6a57d5757ad0a47dac0e9f0bd57b81936f3db" -dependencies = [ - "tracing", - "tracing-subscriber", -] - [[package]] name = "tracing-log" version = "0.2.0" @@ -8204,9 +8701,9 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.20" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" +checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ "matchers", "nu-ansi-term", @@ -8239,38 +8736,42 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" dependencies = [ - "byteorder", "bytes", "data-encoding", "http", "httparse", "log", - "rand 0.8.5", + "rand 0.9.4", "rustls", "rustls-pki-types", "sha1", - "thiserror 1.0.69", + "thiserror 2.0.18", "url", "utf-8", ] [[package]] name = "tungstenite" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +checksum = "6c01152af293afb9c7c2a57e4b559c5620b421f6d133261c60dd2d0cdb38e6b8" dependencies = [ "bytes", "log", - "rand 0.9.2", - "thiserror 2.0.16", - "utf-8", + "rand 0.9.4", + "thiserror 2.0.18", ] +[[package]] +name = "typed-path" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e28f89b80c87b8fb0cf04ab448d5dd0dd0ade2f8891bae878de66a75a28600e" + [[package]] name = "typeid" version = "1.0.3" @@ -8279,9 +8780,9 @@ checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" [[package]] name = "typenum" -version = "1.18.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ucd-trie" @@ -8289,58 +8790,28 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" -[[package]] -name = "ug" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90b70b37e9074642bc5f60bb23247fd072a84314ca9e71cdf8527593406a0dd3" -dependencies = [ - "gemm 0.18.2", - "half", - "libloading", - "memmap2", - "num", - "num-traits", - "num_cpus", - "rayon", - "safetensors", - "serde", - "thiserror 1.0.69", - "tracing", - "yoke 0.7.5", -] - [[package]] name = "ulid" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "470dbf6591da1b39d43c14523b2b469c86879a53e8b758c8e090a470fe7b1fbe" dependencies = [ - "rand 0.9.2", + "rand 0.9.4", "serde", "web-time", ] [[package]] name = "unicase" -version = "2.8.1" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539" +checksum = "dbc4bc3a9f746d862c45cb89d705aa10f187bb96c76001afab07a0d35ce60142" [[package]] name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-normalization" -version = "0.1.24" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" -dependencies = [ - "tinyvec", -] +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" [[package]] name = "unicode-normalization-alignments" @@ -8351,39 +8822,17 @@ dependencies = [ "smallvec", ] -[[package]] -name = "unicode-script" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb421b350c9aff471779e262955939f565ec18b86c15364e6bdf0d662ca7c1f" - -[[package]] -name = "unicode-security" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e4ddba1535dd35ed8b61c52166b7155d7f4e4b8847cec6f48e71dc66d8b5e50" -dependencies = [ - "unicode-normalization", - "unicode-script", -] - [[package]] name = "unicode-segmentation" -version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" - -[[package]] -name = "unicode-width" -version = "0.1.14" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" +checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" [[package]] name = "unicode-width" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" [[package]] name = "unicode-xid" @@ -8397,6 +8846,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" +[[package]] +name = "unit-prefix" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" + [[package]] name = "universal-hash" version = "0.5.1" @@ -8413,12 +8868,24 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39abd59bf32521c7f2301b52d05a6a2c975b6003521cbd0c6dc1582f0a22104" +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" +[[package]] +name = "unty" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d49784317cd0d1ee7ec5c716dd598ec5b4483ea832a2dced265471cc0f690ae" + [[package]] name = "ureq" version = "2.12.1" @@ -8441,9 +8908,9 @@ dependencies = [ [[package]] name = "url" -version = "2.5.7" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" dependencies = [ "form_urlencoded", "idna", @@ -8465,9 +8932,9 @@ checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" [[package]] name = "utf8-width" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" +checksum = "1292c0d970b54115d14f2492fe0170adf21d68a1de108eebc51c1df4f346a091" [[package]] name = "utf8_iter" @@ -8483,13 +8950,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.18.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2" +checksum = "d258b83ceec21034727ecee8c382cfa6c3e133699b0742c64571814fb420c9f7" dependencies = [ - "getrandom 0.3.3", + "getrandom 0.4.2", "js-sys", - "serde", + "serde_core", "wasm-bindgen", ] @@ -8499,12 +8966,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" -[[package]] -name = "vart" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87782b74f898179396e93c0efabb38de0d58d50bbd47eae00c71b3a1144dbbae" - [[package]] name = "vart" version = "0.9.3" @@ -8519,9 +8980,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "veil" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f00796f9c5969da55497f5c8802c2e69eaf21c0166fe28b6006c7c4699f4d0e" +checksum = "c7352f0bbf3ab98911b0c0277065094c1b1ec79bbc85fa3b7d16bf1859c3d96f" dependencies = [ "once_cell", "veil-macros", @@ -8529,13 +8990,13 @@ dependencies = [ [[package]] name = "veil-macros" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b2d5567b6fbd34e8f0488d56b648e67c0d999535f4af2060d14f9074b43e833" +checksum = "47a3f4f06d904eb789b935253752ba6bcc1dfa61349f8d5341c66abe070b44e5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -8544,6 +9005,12 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "virtue" +version = "0.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "051eb1abcf10076295e815102942cc58f9d5e3b4560e46e53c21e8ff6f3af7b1" + [[package]] name = "walkdir" version = "2.5.0" @@ -8570,59 +9037,52 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" [[package]] -name = "wasi" -version = "0.14.4+wasi-0.2.4" +name = "wasip2" +version = "1.0.3+wasi-0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88a5f4a424faf49c3c2c344f166f0662341d470ea185e939657aaff130f0ec4a" +checksum = "20064672db26d7cdc89c7798c48a0fdfac8213434a1186e5ef29fd560ae223d6" dependencies = [ - "wit-bindgen", + "wit-bindgen 0.57.1", ] [[package]] -name = "wasm-bindgen" -version = "0.2.101" +name = "wasip3" +version = "0.4.0+wasi-0.3.0-rc-2026-01-06" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e14915cadd45b529bb8d1f343c4ed0ac1de926144b746e2710f9cd05df6603b" +checksum = "5428f8bf88ea5ddc08faddef2ac4a67e390b88186c703ce6dbd955e1c145aca5" dependencies = [ - "cfg-if", - "once_cell", - "rustversion", - "wasm-bindgen-macro", - "wasm-bindgen-shared", + "wit-bindgen 0.51.0", ] [[package]] -name = "wasm-bindgen-backend" -version = "0.2.101" +name = "wasm-bindgen" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e28d1ba982ca7923fd01448d5c30c6864d0a14109560296a162f80f305fb93bb" +checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409" dependencies = [ - "bumpalo", - "log", - "proc-macro2", - "quote", - "syn 2.0.106", + "cfg-if", + "once_cell", + "rustversion", + "serde", + "wasm-bindgen-macro", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.51" +version = "0.4.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ca85039a9b469b38336411d6d6ced91f3fc87109a2a27b0c197663f5144dffe" +checksum = "9473dbd2991ae90b6291c3c32c30c6187ac49aa32f9905d1cce280ec1e110b0f" dependencies = [ - "cfg-if", "js-sys", - "once_cell", "wasm-bindgen", - "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.101" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d463ae3eff775b0c45df9da45d68837702ac35af998361e2c84e7c5ec1b0d" +checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -8630,26 +9090,48 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.101" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bb4ce89b08211f923caf51d527662b75bdc9c9c7aab40f86dcb9fb85ac552aa" +checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e" dependencies = [ + "bumpalo", "proc-macro2", "quote", - "syn 2.0.106", - "wasm-bindgen-backend", + "syn 2.0.117", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.101" +version = "0.2.122" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f143854a3b13752c6950862c906306adb27c7e839f7414cec8fea35beab624c1" +checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437" dependencies = [ "unicode-ident", ] +[[package]] +name = "wasm-encoder" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "990065f2fe63003fe337b932cfb5e3b80e0b4d0f5ff650e6985b1048f62c8319" +dependencies = [ + "leb128fmt", + "wasmparser", +] + +[[package]] +name = "wasm-metadata" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb0e353e6a2fbdc176932bbaab493762eb1255a7900fe0fea1a2f96c296cc909" +dependencies = [ + "anyhow", + "indexmap", + "wasm-encoder", + "wasmparser", +] + [[package]] name = "wasm-streams" version = "0.4.2" @@ -8663,11 +9145,36 @@ dependencies = [ "web-sys", ] +[[package]] +name = "wasm-streams" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "wasmparser" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" +dependencies = [ + "bitflags", + "hashbrown 0.15.5", + "indexmap", + "semver", +] + [[package]] name = "wasmtimer" -version = "0.2.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7ed9d8b15c7fb594d72bfb4b5a276f3d2029333cd93a932f376f5937f6f80ee" +checksum = "1c598d6b99ea013e35844697fc4670d08339d5cda15588f193c6beedd12f644b" dependencies = [ "futures", "js-sys", @@ -8678,9 +9185,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.78" +version = "0.3.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e4b637749ff0d92b8fad63aa1f7cff3cbe125fd49c175cd6345e7272638b12" +checksum = "6d621441cfc37b84979402712047321980c178f299193a3589d05b99e8763436" dependencies = [ "js-sys", "wasm-bindgen", @@ -8702,10 +9209,31 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57ffde1dc01240bdf9992e3205668b235e59421fd085e8a317ed98da0178d414" dependencies = [ - "phf", - "phf_codegen", - "string_cache", - "string_cache_codegen", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache 0.8.9", + "string_cache_codegen 0.5.4", +] + +[[package]] +name = "web_atoms" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7cff6eef815df1834fd250e3a2ff436044d82a9f1bc1980ca1dbdf07effc538" +dependencies = [ + "phf 0.13.1", + "phf_codegen 0.13.1", + "string_cache 0.9.0", + "string_cache_codegen 0.6.1", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31141ce3fc3e300ae89b78c0dd67f9708061d1d2eda54b8209346fd6be9a92c" +dependencies = [ + "rustls-pki-types", ] [[package]] @@ -8714,14 +9242,14 @@ version = "0.26.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" dependencies = [ - "webpki-roots 1.0.2", + "webpki-roots 1.0.7", ] [[package]] name = "webpki-roots" -version = "1.0.2" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2" +checksum = "52f5ee44c96cf55f1b349600768e3ece3a8f26010c05265ab73f945bb1a2eb9d" dependencies = [ "rustls-pki-types", ] @@ -8748,7 +9276,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.61.0", + "windows-sys 0.61.2", ] [[package]] @@ -8759,24 +9287,24 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows" -version = "0.57.0" +version = "0.61.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" dependencies = [ - "windows-core 0.57.0", - "windows-targets 0.52.6", + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", ] [[package]] -name = "windows-core" -version = "0.57.0" +name = "windows-collections" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" dependencies = [ - "windows-implement 0.57.0", - "windows-interface 0.57.0", - "windows-result 0.1.2", - "windows-targets 0.52.6", + "windows-core 0.61.2", ] [[package]] @@ -8785,55 +9313,57 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" dependencies = [ - "windows-implement 0.60.0", - "windows-interface 0.59.1", + "windows-implement", + "windows-interface", "windows-link 0.1.3", "windows-result 0.3.4", - "windows-strings", + "windows-strings 0.4.2", ] [[package]] -name = "windows-implement" -version = "0.57.0" +name = "windows-core" +version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] -name = "windows-implement" -version = "0.60.0" +name = "windows-future" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", ] [[package]] -name = "windows-interface" -version = "0.57.0" +name = "windows-implement" +version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "windows-interface" -version = "0.59.1" +version = "0.59.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] @@ -8844,28 +9374,29 @@ checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-registry" -version = "0.5.3" +name = "windows-numerics" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a9ed28765efc97bbc954883f4e6796c33a06546ebafacbabee9696967499e" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" dependencies = [ + "windows-core 0.61.2", "windows-link 0.1.3", - "windows-result 0.3.4", - "windows-strings", ] [[package]] -name = "windows-result" -version = "0.1.2" +name = "windows-registry" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-targets 0.52.6", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", ] [[package]] @@ -8877,6 +9408,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-result" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-strings" version = "0.4.2" @@ -8886,6 +9426,15 @@ dependencies = [ "windows-link 0.1.3", ] +[[package]] +name = "windows-strings" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -8919,16 +9468,16 @@ version = "0.60.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" dependencies = [ - "windows-targets 0.53.3", + "windows-targets 0.53.5", ] [[package]] name = "windows-sys" -version = "0.61.0" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e201184e40b2ede64bc2ea34968b28e33622acdbbf37104f0e4a33f7abe657aa" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link 0.2.0", + "windows-link 0.2.1", ] [[package]] @@ -8964,19 +9513,28 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.53.3" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link 0.2.1", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", +] + +[[package]] +name = "windows-threading" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" dependencies = [ "windows-link 0.1.3", - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", ] [[package]] @@ -8993,9 +9551,9 @@ checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" [[package]] name = "windows_aarch64_msvc" @@ -9011,9 +9569,9 @@ checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_aarch64_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" [[package]] name = "windows_i686_gnu" @@ -9029,9 +9587,9 @@ checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" [[package]] name = "windows_i686_gnullvm" @@ -9041,9 +9599,9 @@ checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" [[package]] name = "windows_i686_msvc" @@ -9059,9 +9617,9 @@ checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_i686_msvc" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" [[package]] name = "windows_x86_64_gnu" @@ -9077,9 +9635,9 @@ checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnu" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" [[package]] name = "windows_x86_64_gnullvm" @@ -9095,9 +9653,9 @@ checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_gnullvm" -version = "0.53.0" +version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" [[package]] name = "windows_x86_64_msvc" @@ -9113,24 +9671,121 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "windows_x86_64_msvc" -version = "0.53.0" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + +[[package]] +name = "winnow" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] [[package]] name = "winnow" -version = "0.7.13" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "0592e1c9d151f854e6fd382574c3a0855250e1d9b2f99d9281c6e6391af352f1" dependencies = [ "memchr", ] [[package]] name = "wit-bindgen" -version = "0.45.1" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" +dependencies = [ + "wit-bindgen-rust-macro", +] + +[[package]] +name = "wit-bindgen" +version = "0.57.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" + +[[package]] +name = "wit-bindgen-core" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea61de684c3ea68cb082b7a88508a8b27fcc8b797d738bfc99a82facf1d752dc" +dependencies = [ + "anyhow", + "heck 0.5.0", + "wit-parser", +] + +[[package]] +name = "wit-bindgen-rust" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7c566e0f4b284dd6561c786d9cb0142da491f46a9fbed79ea69cdad5db17f21" +dependencies = [ + "anyhow", + "heck 0.5.0", + "indexmap", + "prettyplease", + "syn 2.0.117", + "wasm-metadata", + "wit-bindgen-core", + "wit-component", +] + +[[package]] +name = "wit-bindgen-rust-macro" +version = "0.51.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c0f9bfd77e6a48eccf51359e3ae77140a7f50b1e2ebfe62422d8afdaffab17a" +dependencies = [ + "anyhow", + "prettyplease", + "proc-macro2", + "quote", + "syn 2.0.117", + "wit-bindgen-core", + "wit-bindgen-rust", +] + +[[package]] +name = "wit-component" +version = "0.244.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" +dependencies = [ + "anyhow", + "bitflags", + "indexmap", + "log", + "serde", + "serde_derive", + "serde_json", + "wasm-encoder", + "wasm-metadata", + "wasmparser", + "wit-parser", +] + +[[package]] +name = "wit-parser" +version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c573471f125075647d03df72e026074b7203790d41351cd6edc96f46bcccd36" +checksum = "ecc8ac4bc1dc3381b7f59c34f00b67e18f910c2c0f50015669dde7def656a736" +dependencies = [ + "anyhow", + "id-arena", + "indexmap", + "log", + "semver", + "serde", + "serde_derive", + "serde_json", + "unicode-xid", + "wasmparser", +] [[package]] name = "workshop-walker" @@ -9145,10 +9800,12 @@ dependencies = [ "itertools 0.14.0", "lingua", "macros", + "migrations-tool", "multimap", "ractor", - "reqwest", + "reqwest 0.13.4", "salvo", + "scraper", "serde", "serde-content", "serde-hack", @@ -9158,8 +9815,10 @@ dependencies = [ "snafu", "str-macro", "surrealdb", - "surrealdb-migrations", + "surrealdb-core", + "surrealdb-types", "tokio", + "tokio-stream", "tracing", "tracing-subscriber", "veil", @@ -9167,36 +9826,35 @@ dependencies = [ [[package]] name = "writeable" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" [[package]] -name = "ws_stream_wasm" -version = "0.7.5" +name = "wyz" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c173014acad22e83f16403ee360115b38846fe754e735c5d9d3803fe70c6abc" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" dependencies = [ - "async_io_stream", - "futures", - "js-sys", - "log", - "pharos", - "rustc_version", - "send_wrapper", - "thiserror 2.0.16", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "tap", ] [[package]] -name = "wyz" -version = "0.5.1" +name = "x509-parser" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "d43b0f71ce057da06bc0851b23ee24f3f86190b07203dd8f567d0b706a185202" dependencies = [ - "tap", + "asn1-rs", + "data-encoding", + "der-parser", + "lazy_static", + "nom", + "oid-registry", + "ring", + "rusticata-macros", + "thiserror 2.0.18", + "time", ] [[package]] @@ -9210,10 +9868,10 @@ dependencies = [ ] [[package]] -name = "xml-rs" -version = "0.8.27" +name = "xml" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fd8403733700263c6eb89f192880191f1b83e332f7a20371ddcf421c4a337c7" +checksum = "636f85e5ca6488e96401b61eb7de54f4e44755c988af0f52cf90230c312a1a89" [[package]] name = "xxhash-rust" @@ -9223,9 +9881,9 @@ checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" [[package]] name = "yaml-rust2" -version = "0.10.3" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce2a4ff45552406d02501cea6c18d8a7e50228e7736a872951fe2fe75c91be7" +checksum = "631a50d867fafb7093e709d75aaee9e0e0d5deb934021fcea25ac2fe09edc51e" dependencies = [ "arraydeque", "encoding_rs", @@ -9239,148 +9897,150 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] -name = "yoke" -version = "0.7.5" +name = "yasna" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +checksum = "b5f6765e852b9b4dc8e2a76843e4d64d1cea8e79bcde0b6901aea8e7c7f08282" dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive 0.7.5", - "zerofrom", + "bit-vec 0.9.1", + "time", ] [[package]] name = "yoke" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc" +checksum = "abe8c5fda708d9ca3df187cae8bfb9ceda00dd96231bed36e445a1a48e66f9ca" dependencies = [ - "serde", "stable_deref_trait", - "yoke-derive 0.8.0", + "yoke-derive", "zerofrom", ] [[package]] name = "yoke-derive" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.106", - "synstructure", -] - -[[package]] -name = "yoke-derive" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6" +checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.27" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +checksum = "3b065d4f0e55f82fae73202e189638116a87c55ab6b8e6c2721e13dd9d854ad1" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.27" +version = "0.8.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +checksum = "0b631b19d36a892ab55420c92dbc83ccd79274f25be714855d3074aa71cab639" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "zerofrom" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5" +checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272" dependencies = [ "zerofrom-derive", ] [[package]] name = "zerofrom-derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", "synstructure", ] [[package]] name = "zeroize" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] name = "zerotrie" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595" +checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" dependencies = [ "displaydoc", - "yoke 0.8.0", + "yoke", "zerofrom", ] [[package]] name = "zerovec" -version = "0.11.4" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b" +checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" dependencies = [ - "yoke 0.8.0", + "yoke", "zerofrom", "zerovec-derive", ] [[package]] name = "zerovec-derive" -version = "0.11.1" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f" +checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" dependencies = [ "proc-macro2", "quote", - "syn 2.0.106", + "syn 2.0.117", ] [[package]] name = "zip" -version = "1.1.4" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cc23c04387f4da0374be4533ad1208cbb091d5c11d070dfef13676ad6497164" +checksum = "c42e33efc22a0650c311c2ef19115ce232583abbe80850bc8b66509ebef02de0" dependencies = [ - "arbitrary", "crc32fast", - "crossbeam-utils", - "displaydoc", - "indexmap 2.11.0", - "num_enum", - "thiserror 1.0.69", + "indexmap", + "memchr", + "typed-path", ] +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" + [[package]] name = "zstd" version = "0.13.3" @@ -9411,15 +10071,15 @@ dependencies = [ [[package]] name = "zune-core" -version = "0.4.12" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" [[package]] name = "zune-jpeg" -version = "0.4.21" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29ce2c8a9384ad323cf564b67da86e21d3cfdff87908bc1223ed5c99bc792713" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" dependencies = [ "zune-core", ] diff --git a/Cargo.toml b/Cargo.toml index 196c832..258bc3a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,69 +1,125 @@ [workspace] -members = ["macros", "serde-hack", "classification"] +members = [ + "classification", + "macros", + "migrations-tool", + "proc-macros", + "scratch", + "serde-hack", +] [workspace.package] -version = "0.2.0" edition = "2024" license = "MPL-2" +version = "0.2.0" [workspace.dependencies] classification = { path = "./classification" } macros = { path = "./macros" } +migrations-tool = { path = "./migrations-tool" } +proc-macros = { path = "./proc-macros" } serde-hack = { path = "./serde-hack" } +async-stream = "0.3.6" bbscope = "0.2" biscuit-auth = "6.0.0" +blake2 = "0.10.6" candle-core = { version = "0.9" } candle-examples = "0.9" candle-nn = "0.9" candle-transformers = "0.9" chrono = "0.4" +clap = { features = ["derive"], version = "4.6" } config = "0.15" +futures = "0.3.32" hf-hub = "0.4" humantime = "2.2" intel-mkl-src = { version = "0.8" } itertools = "0.14" -lingua = { version = "1.7", features = ["english", "russian", "chinese", "japanese", "korean"] } +lingua = { features = [ + "chinese", + "english", + "french", + "japanese", + "korean", + "russian", +], version = "1.7" } multimap = "0.10" -ractor = { version = "0.15", features = ["monitors", "async-trait"] } -reqwest = { version = "0.12", features = ["json", ] } -salvo = { version = "0.85", features = ["oapi", "logging", "serve-static", "affix-state", "cookie", "size-limiter"] } -serde = { version = "1.0", features = ["derive"] } +paste = "1.0" +quote = "1.0" +ractor = { features = ["async-trait", "monitors"], version = "0.15" } +reqwest = { features = ["json"], version = "0.13" } +salvo = { features = [ + "affix-state", + "cookie", + "logging", + "oapi", + "serve-static", + "size-limiter", +], version = "0.89" } +scraper = "0.25" +serde = { features = ["derive"], version = "1.0" } serde-content = "0.1" serde-xml-rs = "0.8.1" serde_json = "1.0" serde_repr = "0.1" -snafu = "0.8" +snafu = "0.9" str-macro = "1" -surrealdb = { version = "2.4", features = ["kv-rocksdb", "allocator", "protocol-http", "protocol-ws", "rustls", "kv-mem"] } -surrealdb-migrations = "2.2" -tokenizers = "0.21" -tokio = { version = "1.48", features = ["full"] } +surrealdb = { features = [ + "allocator", + "kv-mem", + "kv-rocksdb", + "protocol-http", + "protocol-ws", + "rustls", +], version = "3.1" } +surrealdb-core = "3.1" +surrealdb-types = "3.1" +syn = "2.0" +tempfile = "3.27.0" +tokenizers = "0.22" +tokio = { features = ["full"], version = "1.48" } +tokio-stream = { features = ["fs"], version = "0.1" } tracing = "0.1" -tracing-subscriber = { version = "0.3.19", features = ["env-filter"] } -veil = "0.2" +tracing-subscriber = { features = ["env-filter"], version = "0.3.19" } +veil = "0.3" [package] -name = "workshop-walker" -version.workspace = true edition.workspace = true license.workspace = true +name = "workshop-walker" +version.workspace = true [dependencies] bbscope.workspace = true biscuit-auth.workspace = true chrono.workspace = true -classification = { workspace = true, optional = true } +classification = { optional = true, workspace = true } config.workspace = true humantime.workspace = true itertools.workspace = true -lingua = { workspace = true, features = ["english", "russian", "chinese", "japanese", "korean"] } +lingua = { features = [ + "chinese", + "english", + "japanese", + "korean", + "russian", +], workspace = true } macros.workspace = true +migrations-tool.workspace = true multimap.workspace = true -ractor = { workspace = true, features = ["monitors", "async-trait"] } -reqwest = { workspace = true, features = ["json", ] } -salvo = { workspace = true, features = ["oapi", "logging", "serve-static", "affix-state", "cookie", "size-limiter"] } -serde = { workspace = true, features = ["derive"] } +ractor = { features = ["async-trait", "monitors"], workspace = true } +reqwest = { features = ["json", "query"], version = "1.0.0", workspace = true } +salvo = { features = [ + "affix-state", + "cookie", + "logging", + "oapi", + "serve-static", + "size-limiter", +], workspace = true } +scraper.workspace = true +serde = { features = ["derive"], workspace = true } serde-content.workspace = true serde-hack.workspace = true serde-xml-rs.workspace = true @@ -71,11 +127,26 @@ serde_json.workspace = true serde_repr.workspace = true snafu.workspace = true str-macro.workspace = true -surrealdb = { workspace = true, features = ["kv-rocksdb", "allocator", "protocol-http", "protocol-ws", "rustls", "kv-mem"] } -surrealdb-migrations.workspace = true -tokio = { workspace = true, features = ["rt", "rt-multi-thread", "macros", "fs", "sync"] } -tracing-subscriber = { workspace = true, features = ["env-filter"] } +surrealdb = { features = [ + "allocator", + "kv-mem", + "kv-rocksdb", + "protocol-http", + "protocol-ws", + "rustls", +], workspace = true } +surrealdb-core.workspace = true +surrealdb-types.workspace = true +tokio = { features = [ + "fs", + "macros", + "rt", + "rt-multi-thread", + "sync", +], workspace = true } +tokio-stream.workspace = true tracing.workspace = true +tracing-subscriber = { features = ["env-filter"], workspace = true } veil.workspace = true [features] @@ -84,7 +155,9 @@ ml-classification = ["classification", "classification/mkl"] [patch.crates-io] -surrealdb-migrations = { git = "https://github.com/disconsented/surrealdb-migrations.git" } +surrealdb = { path = "../surrealdb/surrealdb" } +surrealdb-core = { path = "../surrealdb/surrealdb/core" } +surrealdb-types = { path = "../surrealdb/surrealdb/types" } [profile.release] lto = true @@ -93,19 +166,19 @@ panic = 'abort' #codegen-units = 1 [profile.dev.package."*"] -opt-level = 3 +#opt-level = 3 [lints.clippy] -lint_groups_priority = { level = "allow", priority = 0 } -suspicious = { level = "deny", priority = 1 } -style = { level = "deny", priority = 2 } -perf = { level = "deny", priority = 4 } -pedantic = { level = "deny", priority = 5 } -correctness = { level = "deny", priority = 6 } +allow-dbg-in-tests = { level = "allow", priority = 9 } complexity = { level = "warn", priority = 7 } +correctness = { level = "deny", priority = 6 } dbg_macro = { level = "deny", priority = 8 } -allow-dbg-in-tests = { level = "allow", priority = 9 } +lint_groups_priority = { level = "allow", priority = 0 } +pedantic = { level = "deny", priority = 5 } +perf = { level = "deny", priority = 4 } pub_with_shorthand = { level = "allow", priority = 10 } +style = { level = "deny", priority = 2 } +suspicious = { level = "deny", priority = 1 } [target.x86_64-unknown-linux-gnu] rustflags = "-C target-cpu=x86-64-v3" diff --git a/classification/Cargo.toml b/classification/Cargo.toml index 470bd9e..4fc98fc 100644 --- a/classification/Cargo.toml +++ b/classification/Cargo.toml @@ -1,23 +1,23 @@ [package] +edition.workspace = true name = "classification" version.workspace = true -edition.workspace = true [dependencies] -snafu.workspace = true candle-core.workspace = true -intel-mkl-src = { workspace = true, optional = true } -candle-transformers.workspace = true +candle-examples.workspace = true candle-nn.workspace = true +candle-transformers.workspace = true hf-hub.workspace = true -tokenizers.workspace = true -serde_json.workspace = true -candle-examples.workspace = true -serde = { workspace = true, features = ["derive"] } -tracing.workspace = true +intel-mkl-src = { optional = true, workspace = true } ractor.workspace = true +serde = { features = ["derive"], workspace = true } +serde_json.workspace = true +snafu.workspace = true +tokenizers.workspace = true tokio.workspace = true +tracing.workspace = true [features] default = ["mkl"] -mkl = ["dep:intel-mkl-src", "candle-core/mkl"] \ No newline at end of file +mkl = ["candle-core/mkl", "dep:intel-mkl-src"] diff --git a/classification/src/lib.rs b/classification/src/lib.rs index b45f511..b9174f5 100644 --- a/classification/src/lib.rs +++ b/classification/src/lib.rs @@ -4,12 +4,10 @@ pub mod actor; mod hub; mod runner; -use std::backtrace::Backtrace; - -use snafu::{ResultExt, Snafu, whatever}; - const MODEL_ID: &str = "mistralai/Mistral-7B-Instruct-v0.2"; +use std::backtrace::Backtrace; + use candle_core::{DType, Device, Tensor}; use candle_examples::token_output_stream::TokenOutputStream; use candle_transformers::{ @@ -17,7 +15,8 @@ use candle_transformers::{ models::mistral::Model, }; use serde::{Deserialize, Serialize}; -use tokenizers::Tokenizer; +use snafu::{ResultExt, Snafu, whatever}; +use tokenizers::tokenizer::Tokenizer; use tracing::{debug, instrument}; #[derive(Debug, Snafu)] @@ -87,10 +86,11 @@ pub enum Error { #[derive(Debug, Snafu)] #[snafu(whatever)] #[snafu(display("{message}"))] -#[snafu(provide(opt, ref, chain, dyn std::error::Error + Send + Sync => source.as_deref()))] +// #[snafu(provide(opt, ref, chain, dyn std::error::Error + Send + Sync => +// source.as_deref()))] pub struct WhateverAsync { #[snafu(source(from(Box, Some)))] - #[snafu(provide(false))] + // #[snafu(provide(false))] source: Option>, message: String, backtrace: Backtrace, diff --git a/classification/src/runner.rs b/classification/src/runner.rs index 7c649c0..8a54df1 100644 --- a/classification/src/runner.rs +++ b/classification/src/runner.rs @@ -6,6 +6,7 @@ use snafu::ResultExt; use tokenizers::Tokenizer; use tokio::{ sync::{mpsc, oneshot}, + task, task::{JoinHandle, spawn_blocking}, }; use tracing::{Instrument, info_span, warn}; @@ -21,6 +22,10 @@ pub struct PipelineRunner { } impl PipelineRunner { pub async fn setup() -> Result { + return Ok(Self { + pipeline_task: task::spawn(async {}), + pipeline_tx: mpsc::channel(1).0, + }); let span = info_span!("PipelineRunner::setup"); let _g = span.enter(); let api = Api::new().map_err(|e| Error::ApiInit { diff --git a/clippy.toml b/clippy.toml index df8bf28..b8a52b5 100644 --- a/clippy.toml +++ b/clippy.toml @@ -1,2 +1,4 @@ allow-unwrap-in-tests = true -allow-dbg-in-tests = true \ No newline at end of file +allow-dbg-in-tests = true +allow-unwrap-types = ["std::sync::LockResult"] +disallowed-methods = ["surrealdb_types::value::record_id::RecordId::new"] \ No newline at end of file diff --git a/macros/Cargo.toml b/macros/Cargo.toml index 233272b..07c337c 100644 --- a/macros/Cargo.toml +++ b/macros/Cargo.toml @@ -1,7 +1,11 @@ [package] +edition.workspace = true name = "macros" version.workspace = true -edition.workspace = true + [dependencies] -serde = { version = "1.0.219", features = ["derive"] } +paste.workspace = true +proc-macros.workspace = true +serde.workspace = true +serde_json.workspace = true diff --git a/macros/src/lib.rs b/macros/src/lib.rs index 90dce22..37efb22 100644 --- a/macros/src/lib.rs +++ b/macros/src/lib.rs @@ -1,43 +1,107 @@ -/// Table name, type name, underlying key type +pub use proc_macros::dual_struct; + +/// A helper macro to define a newtype for a SurrealDB record ID. +/// Makes it not a total pain in the ass to deal with. +/// +/// Implemented with 2 structs because, we can't maintain a transparent newtype +/// with an enum, which, makes sense as its a different type. +/// +/// ## Args: +/// Table name: The name of the SurrealDB table\ +/// Internal name: The name of the internal newtype (interfaces with the DB)\ +/// External name: The name of the external newtype (exposed to users)\ +/// External type: The underlying type of the external newtype #[macro_export] macro_rules! define_id { - ($table:literal, $name:ident, $type:ty) => { - /// A SurrealDB ID abstraction to work around some points of pain - #[derive(serde::Serialize, serde::Deserialize, Clone, Debug)] + ($table:literal, $internal:ident, $external:ident, $external_type:ty) => { + /// Externally facing newtype over $external_type + #[derive( + serde::Serialize, + serde::Deserialize, + Clone, + Debug, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + salvo::prelude::ToSchema, + )] + #[serde(transparent)] + pub struct $external($external_type); + impl From<$external> for $external_type { + fn from(id: $external) -> $external_type { + id.0 + } + } + + impl From<$external_type> for $external { + fn from(id: $external_type) -> Self { + Self(id) + } + } + /// Internally facing newtype over RecordID + #[derive( + serde::Serialize, + serde::Deserialize, + Clone, + Debug, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + surrealdb_types::SurrealValue, + )] #[serde(transparent)] - pub struct $name($type); - impl $name { + pub struct $internal(surrealdb_types::RecordId); + impl $internal { const TABLE_NAME: &'static str = $table; - pub fn into_recordid(self) -> surrealdb::RecordId { - Into::::into(self) + // An alias of TryInto<$external> for $internal to make it easier to use + pub fn try_into_external(self) -> Result<$external, surrealdb_types::Error> { + self.try_into() } } - impl Into for $name { - fn into(self) -> surrealdb::RecordId { - surrealdb::RecordId::from_table_key(Self::TABLE_NAME, self.0) + impl From<$external> for $internal { + fn from(id: $external) -> Self { + #[allow( + clippy::disallowed_methods, + reason = "Macro use only, this is considered correct" + )] + Self(surrealdb_types::RecordId::new(Self::TABLE_NAME, id.0)) } } - impl Into<$type> for $name { - fn into(self) -> $type { - self.0 + impl From<$external_type> for $internal { + fn from(id: $external_type) -> Self { + #[allow( + clippy::disallowed_methods, + reason = "Macro use only, this is considered correct" + )] + Self(surrealdb_types::RecordId::new(Self::TABLE_NAME, id)) } } - impl From<$type> for $name { - fn from(value: $type) -> Self { - Self(value) + impl From<$internal> for surrealdb_types::RecordId { + fn from(id: $internal) -> surrealdb_types::RecordId { + id.0 + } + } + + impl TryFrom<$internal> for $external { + type Error = surrealdb_types::Error; + + fn try_from(id: $internal) -> Result<$external, Self::Error> { + Ok($external(id.0.key.into_value().into_t()?)) + } + } + + impl std::ops::Deref for $internal { + type Target = surrealdb_types::RecordId; + + fn deref(&self) -> &Self::Target { + &self.0 } } }; } -// #[macro_export] -// macro_rules! define_dual { -// ($($id:ident : $type:ty),* $(,)?) => { -// #[derive(serde::Serialize, serde::Deserialize)] -// struct Test { -// pub id: String, -// $($id : $type),* -// } -// }; -// } diff --git a/manual_db_migrations b/manual_db_migrations new file mode 100644 index 0000000..4cd897f --- /dev/null +++ b/manual_db_migrations @@ -0,0 +1,14 @@ +-- Delete rows that are set extensions like `-- DEFINE FIELD default_tags.* ON apps TYPE record REFERENCE PERMISSIONS FULL;` + +DEFINE TABLE usernames TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; +DEFINE FIELD username ON usernames TYPE record REFERENCE PERMISSIONS FULL; +DEFINE FIELD last_updated ON usernames TYPE datetime PERMISSIONS FULL; +DEFINE FIELD name ON usernames TYPE string PERMISSIONS FULL; +DEFINE INDEX unique_username ON usernames FIELDS username; +-- renamed id to username + +-- id:usernames: +-- username:usernames: + +-- INSERT [{username:usernames: +-- INSERT INTO usernames [{username:usernames: \ No newline at end of file diff --git a/migrations-tool/Cargo.toml b/migrations-tool/Cargo.toml new file mode 100644 index 0000000..9a83d10 --- /dev/null +++ b/migrations-tool/Cargo.toml @@ -0,0 +1,26 @@ +[package] +edition.workspace = true +license.workspace = true +name = "migrations-tool" +version.workspace = true + +[lib] +name = "migrations_tool" +path = "src/lib.rs" + +[dependencies] +async-stream.workspace = true +blake2.workspace = true +chrono = { features = ["serde"], workspace = true } +clap = { features = ["derive"], workspace = true } +futures.workspace = true +serde = { features = ["derive"], workspace = true } +snafu.workspace = true +surrealdb.workspace = true +tracing.workspace = true + +[dev-dependencies] +serde_json.workspace = true +tempfile.workspace = true +tokio.workspace = true +tracing-subscriber.workspace = true diff --git a/migrations-tool/README.md b/migrations-tool/README.md new file mode 100644 index 0000000..0ea27ad --- /dev/null +++ b/migrations-tool/README.md @@ -0,0 +1,124 @@ +> **⚠️ AI-Generated Code** +> +> This crate was built with [Claude](https://anthropic.com) (Anthropic AI assistance). +> It has not been independently audited. Review the logic carefully before deploying +> to a production environment or trusting it with critical data. + +# migrations-tool + +A type-driven, async, **up-only** migration runner for [SurrealDB](https://surrealdb.com). +Works with any connection type (`Mem`, `RocksDb`, `Ws`, `Http`, …) via the generic +`Surreal` API. + +## Quickstart + +```rust +use futures::StreamExt as _; +use migrations_tool::{Migrator, Outcome}; + +// Connect to SurrealDB however you like, then: +let plan = Migrator::from_files("./migrations")? + .with_table("_migrations") // default — can be omitted + .ignore_checksum_changes(false) // default — can be omitted + .validate()? + .plan(&db) + .await?; + +println!("will apply {} migrations", plan.pending().len()); + +let mut stream = std::pin::pin!(plan.execute(&db)); +while let Some(outcome) = stream.next().await { + match outcome? { + Outcome::Applied { id, duration } => println!("applied {id} in {duration:?}"), + Outcome::Skipped { id, .. } => println!("skipped {id}"), + } +} +``` + +## File layout + +Place `.surql` files in a single directory. The runner loads every `*.surql` file +**non-recursively** and sorts them **lexicographically by filename**. No timestamp +parsing is performed — sort order is entirely determined by the filename string. + +A timestamp prefix (e.g. `1779584187_baseline.surql`) works well because it is +fixed-width for any foreseeable epoch value. + +- `Migration::id` = full filename (`1779584187_baseline.surql`) +- `Migration::name` = same as `id` + +## Typestate flow + +``` +Migrator ← from_files() / from_strings() + .with_table("…") ┐ + .ignore_checksum_changes(…)┘ builder methods — only here + .validate()? → Migrator + .plan(&db).await? → Plan + .execute(&db) → impl Stream> +``` + +- **`validate()`** — connection-free; checks for duplicate IDs and empty content. + Collects all duplicate IDs in a single error rather than stopping at the first. +- **`plan()`** — queries the state table; classifies each migration as pending, + skipped, or errors with `ChecksumMismatch`. +- **`execute()`** — drives the stream; applies one migration per `next()` call. + Halts on the first error. + +## Checksums + +Every migration's `content` is hashed with **BLAKE2b-256** (32-byte output, +lowercase hex) when it is first applied. On subsequent runs the stored hash is +compared against the hash of the file as it exists on disk. + +A mismatch means the migration was edited after it was applied and `plan()` returns +`Error::ChecksumMismatch`. + +To downgrade the mismatch from an error to a skip with a warning: + +```rust +Migrator::from_files("./migrations")? + .ignore_checksum_changes(true) + .validate()? + .plan(&db) + .await?; +``` + +## State table schema + +The runner maintains a table (default `_migrations`) with one record per applied +migration: + +| field | type | description | +|---------------|----------|--------------------------------------| +| `id` | record | `_migrations:⟨migration-id⟩` | +| `name` | string | human label (= `id` for file source) | +| `checksum` | string | BLAKE2b-256 hex of `content` | +| `applied_at` | datetime | server-side `time::now()` | +| `duration_ms` | int | wall-clock ms from tx start to commit| + +## Error handling + +All errors are variants of the single `Error` enum (powered by +[snafu](https://docs.rs/snafu)): + +| variant | when | +|---------------------|----------------------------------------------------------| +| `Io` | reading a migration file fails | +| `InvalidUtf8` | a migration file is not valid UTF-8 | +| `DuplicateIds` | two migrations share the same ID | +| `EmptyContent` | a migration has blank content | +| `ChecksumMismatch` | content changed after it was applied; use `ignore_…(true)` to bypass | +| `StateQuery` | querying the state table fails | +| `MigrationFailed` | executing a migration's SurrealQL fails | +| `Surreal` | other SurrealDB client errors | + +## Testing + +```sh +# in-memory engine +cargo test --test mem + +# RocksDB engine +cargo test --test rocksdb +``` diff --git a/migrations-tool/src/checksum.rs b/migrations-tool/src/checksum.rs new file mode 100644 index 0000000..349ffd2 --- /dev/null +++ b/migrations-tool/src/checksum.rs @@ -0,0 +1,41 @@ +use blake2::{Blake2b, Digest, digest::consts::U32}; + +type Blake2b256 = Blake2b; + +/// Compute a BLAKE2b-256 checksum over the UTF-8 bytes of `content`. +/// +/// Returns a 64-character lowercase hex string. +pub(crate) fn compute(content: &str) -> String { + let mut hasher = Blake2b256::new(); + hasher.update(content.as_bytes()); + let result = hasher.finalize(); + result.iter().fold(String::with_capacity(64), |mut s, b| { + use std::fmt::Write as _; + let _ = write!(s, "{b:02x}"); + s + }) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn deterministic() { + let a = compute("DEFINE TABLE foo;"); + let b = compute("DEFINE TABLE foo;"); + assert_eq!(a, b); + } + + #[test] + fn different_content_differs() { + let a = compute("DEFINE TABLE foo;"); + let b = compute("DEFINE TABLE bar;"); + assert_ne!(a, b); + } + + #[test] + fn length_is_64() { + assert_eq!(compute("x").len(), 64); + } +} diff --git a/migrations-tool/src/error.rs b/migrations-tool/src/error.rs new file mode 100644 index 0000000..3d35c2d --- /dev/null +++ b/migrations-tool/src/error.rs @@ -0,0 +1,60 @@ +use snafu::Snafu; + +/// All errors produced by the migration runner. +#[derive(Debug, Snafu)] +#[snafu(visibility(pub(crate)))] +pub enum Error { + /// An I/O error reading a migration file. + #[snafu(display("I/O error reading '{}': {source}", path.display()))] + Io { + source: std::io::Error, + path: std::path::PathBuf, + }, + + /// A migration file contained invalid UTF-8. + #[snafu(display("Invalid UTF-8 in '{}': {source}", path.display()))] + InvalidUtf8 { + source: std::string::FromUtf8Error, + path: std::path::PathBuf, + }, + + /// One or more migration IDs appeared more than once. + #[snafu(display("Duplicate migration IDs: {}", ids.join(", ")))] + DuplicateIds { ids: Vec }, + + /// A migration has no SurrealQL content. + #[snafu(display("Migration '{}' has empty content", id))] + EmptyContent { id: String }, + + /// The on-disk checksum differs from the stored checksum. + /// + /// Call `.ignore_checksum_changes(true)` on the migrator to treat this as + /// a skip instead of an error. + #[snafu(display( + "Checksum mismatch for migration '{}'. Set ignore_checksum_changes(true) to bypass.", + id + ))] + ChecksumMismatch { id: String }, + + /// A general SurrealDB client error. + #[snafu(display("SurrealDB error: {source}"))] + Surreal { + #[snafu(source(from(surrealdb::Error, Box::new)))] + source: Box, + }, + + /// An error querying the migration state table. + #[snafu(display("Error querying migration state: {source}"))] + StateQuery { + #[snafu(source(from(surrealdb::Error, Box::new)))] + source: Box, + }, + + /// A migration failed during execution. + #[snafu(display("Migration '{}' failed: {source}", id))] + MigrationFailed { + id: String, + #[snafu(source(from(surrealdb::Error, Box::new)))] + source: Box, + }, +} diff --git a/migrations-tool/src/lib.rs b/migrations-tool/src/lib.rs new file mode 100644 index 0000000..e6dc9f5 --- /dev/null +++ b/migrations-tool/src/lib.rs @@ -0,0 +1,78 @@ +//! # migrations-tool +//! +//! > **AI-generated code.** This crate was built with Claude (Anthropic). +//! > Review +//! > all logic before deploying to production. +//! +//! A type-driven, async, up-only migration runner for [SurrealDB](https://surrealdb.com). +//! +//! ## Quickstart +//! +//! ```rust,no_run +//! use futures::StreamExt as _; +//! use migrations_tool::{Migrator, Outcome}; +//! use surrealdb::Surreal; +//! use surrealdb::engine::any::Any; +//! +//! # async fn example(db: &Surreal) -> Result<(), migrations_tool::Error> { +//! let plan = Migrator::from_files("./migrations")? +//! .with_table("_migrations") +//! .ignore_checksum_changes(false) +//! .validate()? +//! .plan(db) +//! .await?; +//! +//! println!("will apply {} migrations", plan.pending().len()); +//! +//! // The stream is not Unpin; pin it before polling. +//! let mut stream = std::pin::pin!(plan.execute(db)); +//! while let Some(outcome) = stream.next().await { +//! match outcome? { +//! Outcome::Applied { id, duration } => { +//! println!("applied {id} in {:?}", duration); +//! } +//! Outcome::Skipped { id, .. } => { +//! println!("skipped {id}"); +//! } +//! } +//! } +//! # Ok(()) +//! # } +//! ``` +//! +//! ## Typestate flow +//! +//! ```text +//! Migrator +//! .with_table(...) ─┐ builder methods only available here +//! .ignore_checksum_changes(...) ─┘ +//! .validate()? → Migrator +//! .plan(&db).await? → Plan +//! .execute(&db) → impl Stream> +//! ``` +//! +//! - `validate()` is connection-free and checks for duplicate IDs and empty +//! content. +//! - `plan()` queries the state table and classifies each migration. +//! - `execute()` drives the stream; each item is one migration outcome. +//! +//! ## Checksums +//! +//! Every migration's `content` is hashed with **BLAKE2b-256** (32-byte output, +//! hex-encoded) before it is stored in the state table. On the next run the +//! stored hash is compared against the hash of the file as it exists on disk. A +//! mismatch means the migration was edited after it was applied. +//! +//! Call `.ignore_checksum_changes(true)` to skip mismatched migrations with a +//! warning instead of returning [`Error::ChecksumMismatch`]. + +pub use error::Error; +pub use migrator::{Migrator, Unvalidated, Validated}; +pub use plan::Plan; +pub use types::{Migration, Outcome, SkipReason}; + +mod checksum; +mod error; +mod migrator; +mod plan; +mod types; diff --git a/migrations-tool/src/main.rs b/migrations-tool/src/main.rs new file mode 100644 index 0000000..bd504ae --- /dev/null +++ b/migrations-tool/src/main.rs @@ -0,0 +1,38 @@ +use std::{fs, path::PathBuf}; + +use chrono::Utc; +use clap::Parser; + +#[derive(Parser)] +#[command(about = "Create a SurrealDB migration stub file")] +struct Args { + /// Name for the migration (appended after the timestamp) + name: String, + + /// Directory to create the migration in + #[arg(short, long, default_value = "migrations")] + dir: PathBuf, +} + +fn main() { + let args = Args::parse(); + + let ts = Utc::now().timestamp_millis(); + let filename = format!("{}_{}.surql", ts, args.name); + let path = args.dir.join(&filename); + + if let Err(e) = fs::create_dir_all(&args.dir) { + eprintln!( + "error: could not create directory '{}': {e}", + args.dir.display() + ); + std::process::exit(1); + } + + if let Err(e) = fs::write(&path, "") { + eprintln!("error: could not create '{}': {e}", path.display()); + std::process::exit(1); + } + + println!("{}", path.display()); +} diff --git a/migrations-tool/src/migrator.rs b/migrations-tool/src/migrator.rs new file mode 100644 index 0000000..7c70283 --- /dev/null +++ b/migrations-tool/src/migrator.rs @@ -0,0 +1,255 @@ +use std::{collections::HashSet, marker::PhantomData, path::Path}; + +use snafu::ResultExt as _; +use surrealdb::{Connection, Surreal}; +use tracing::{Instrument as _, debug, error, info, info_span, warn}; + +use crate::{ + Error, checksum, + error::{InvalidUtf8Snafu, IoSnafu, StateQuerySnafu}, + plan::Plan, + types::{Migration, SkipReason}, +}; + +/// Typestate marker — builder methods are available, `plan()` is not. +#[derive(Debug)] +pub struct Unvalidated; + +/// Typestate marker — validation passed, `plan()` is available. +#[derive(Debug)] +pub struct Validated; + +/// Async migration runner, parameterised by a typestate `S`. +/// +/// Start with [`Migrator::from_files`] or [`Migrator::from_strings`], configure +/// via builder methods, advance to [`Validated`] via [`Migrator::validate`], +/// then call [`Migrator::plan`]. +#[derive(Debug)] +pub struct Migrator { + pub(crate) migrations: Vec, + pub(crate) table: String, + pub(crate) ignore_checksum_changes: bool, + pub(crate) _state: PhantomData, +} + +impl Migrator { + /// Load every `*.surql` file from `dir`, sorted lexicographically by + /// filename. + /// + /// `Migration::id` and `Migration::name` are both set to the full filename. + pub fn from_files(dir: impl AsRef) -> Result { + let dir = dir.as_ref(); + let mut paths = Vec::new(); + + let entries = std::fs::read_dir(dir).context(IoSnafu { + path: dir.to_path_buf(), + })?; + + for entry in entries { + let entry = entry.context(IoSnafu { + path: dir.to_path_buf(), + })?; + let path = entry.path(); + if path.extension().and_then(|e| e.to_str()) == Some("surql") { + paths.push(path); + } + } + + // Lexicographic sort by filename only (not full path). + paths.sort_by(|a, b| { + a.file_name() + .unwrap_or_default() + .cmp(b.file_name().unwrap_or_default()) + }); + + let mut migrations = Vec::with_capacity(paths.len()); + for path in paths { + let filename = path + .file_name() + .unwrap_or_default() + .to_string_lossy() + .into_owned(); + + let bytes = std::fs::read(&path).context(IoSnafu { path: path.clone() })?; + let content = + String::from_utf8(bytes).context(InvalidUtf8Snafu { path: path.clone() })?; + + migrations.push(Migration { + id: filename.clone(), + name: filename, + content, + }); + } + + Ok(Self::new(migrations)) + } + + /// Use a caller-supplied list of migrations. Order is preserved as given. + pub fn from_strings(migrations: Vec) -> Self { + Self::new(migrations) + } + + /// Override the state-tracking table name (default: `_migrations`). + pub fn with_table(mut self, table: impl Into) -> Self { + self.table = table.into(); + self + } + + /// When `true`, a checksum mismatch for an already-applied migration is + /// treated as a skip rather than an error (a warning is still emitted). + pub fn ignore_checksum_changes(mut self, ignore: bool) -> Self { + self.ignore_checksum_changes = ignore; + self + } + + /// Validate the migration set without touching the database. + /// + /// Collects **all** problems before returning — duplicate IDs are reported + /// together rather than one at a time. + pub fn validate(self) -> Result, Error> { + let mut seen_ids: HashSet = HashSet::new(); + let mut duplicate_ids: Vec = Vec::new(); + + for m in &self.migrations { + if !seen_ids.insert(m.id.clone()) { + duplicate_ids.push(m.id.clone()); + } + } + + if !duplicate_ids.is_empty() { + return Err(Error::DuplicateIds { ids: duplicate_ids }); + } + + for m in &self.migrations { + if m.content.trim().is_empty() { + return Err(Error::EmptyContent { id: m.id.clone() }); + } + } + + debug!( + count = self.migrations.len(), + table = %self.table, + "migrations validated" + ); + + Ok(Migrator { + migrations: self.migrations, + table: self.table, + ignore_checksum_changes: self.ignore_checksum_changes, + _state: PhantomData, + }) + } + + fn new(migrations: Vec) -> Self { + Self { + migrations, + table: "_migrations".to_string(), + ignore_checksum_changes: false, + _state: PhantomData, + } + } +} + +impl Migrator { + /// Query the database to determine which migrations have already been + /// applied, then classify the remaining ones as pending or skipped. + /// + /// Returns [`Error::ChecksumMismatch`] if a migration's content has changed + /// and `ignore_checksum_changes` is `false`. + pub async fn plan(&self, db: &Surreal) -> Result { + let span = info_span!("plan", table = %self.table); + + async { + let applied = self.fetch_applied(db).await?; + self.classify(applied) + } + .instrument(span) + .await + } + + async fn fetch_applied( + &self, + db: &Surreal, + ) -> Result, Error> { + // Ensure the state table exists (no-op if already present). + let define_sql = format!( + "DEFINE TABLE IF NOT EXISTS `{}` SCHEMALESS", + self.table.replace('`', "") + ); + db.query(define_sql) + .await + .context(StateQuerySnafu)? + .check() + .context(StateQuerySnafu)?; + + let mut response = db + .query("SELECT meta::id(id) AS id, checksum FROM type::table($table) ORDER BY id ASC") + .bind(("table", self.table.clone())) + .await + .context(StateQuerySnafu)?; + + let records: Vec = response.take(0).context(StateQuerySnafu)?; + + debug!(count = records.len(), "fetched applied migrations"); + + let applied = records + .into_iter() + .filter_map(|obj| { + let id = obj.get("id")?.as_string()?.clone(); + let checksum = obj.get("checksum")?.as_string()?.clone(); + Some((id, checksum)) + }) + .collect(); + + Ok(applied) + } + + fn classify(&self, applied: std::collections::HashMap) -> Result { + let mut pending = Vec::new(); + let mut skipped = Vec::new(); + + for migration in &self.migrations { + match applied.get(&migration.id) { + None => { + debug!(id = %migration.id, "pending"); + pending.push(migration.clone()); + } + Some(stored_checksum) => { + let current = checksum::compute(&migration.content); + if current == *stored_checksum { + debug!(id = %migration.id, "already applied"); + skipped.push((migration.clone(), SkipReason::AlreadyApplied)); + } else if self.ignore_checksum_changes { + warn!( + id = %migration.id, + stored = %stored_checksum, + current = %current, + "checksum changed but ignore_checksum_changes is set — skipping" + ); + skipped.push((migration.clone(), SkipReason::ChecksumChangedButIgnored)); + } else { + error!( + id = %migration.id, + "checksum mismatch; set ignore_checksum_changes(true) to bypass" + ); + return Err(Error::ChecksumMismatch { + id: migration.id.clone(), + }); + } + } + } + } + + info!( + pending = pending.len(), + skipped = skipped.len(), + "plan ready" + ); + + Ok(Plan { + table: self.table.clone(), + pending, + skipped, + }) + } +} diff --git a/migrations-tool/src/plan.rs b/migrations-tool/src/plan.rs new file mode 100644 index 0000000..baecf91 --- /dev/null +++ b/migrations-tool/src/plan.rs @@ -0,0 +1,130 @@ +use std::time::Instant; + +use async_stream::try_stream; +use futures::Stream; +use snafu::ResultExt as _; +use surrealdb::{Connection, Surreal}; +use tracing::{Instrument as _, info, info_span, trace}; + +use crate::{ + Error, checksum, + error::{MigrationFailedSnafu, SurrealSnafu}, + types::{Migration, Outcome, SkipReason}, +}; + +/// A classified set of migrations ready to execute. +/// +/// Obtain via [`crate::Migrator::plan`]. Inspect [`Plan::pending`] and +/// [`Plan::skipped`] before calling [`Plan::execute`]. +#[derive(Debug)] +pub struct Plan { + pub(crate) table: String, + pub(crate) pending: Vec, + pub(crate) skipped: Vec<(Migration, SkipReason)>, +} + +impl Plan { + /// Migrations that will be applied when [`Plan::execute`] is called. + pub fn pending(&self) -> &[Migration] { + &self.pending + } + + /// Migrations that will be skipped and why. + pub fn skipped(&self) -> &[(Migration, SkipReason)] { + &self.skipped + } + + /// Execute pending migrations in order, yielding one [`Outcome`] per + /// migration. + /// + /// Each migration runs inside a `BEGIN / COMMIT TRANSACTION` block that + /// also inserts the state row, so a failed migration leaves no state + /// behind. + /// + /// The stream halts on the first error — subsequent migrations are not + /// attempted. + pub fn execute<'db, C>( + self, + db: &'db Surreal, + ) -> impl Stream> + 'db + where + C: Connection, + { + let table = self.table; + let pending = self.pending; + + try_stream! { + for migration in pending { + let duration = run_migration(db, &table, &migration).await?; + yield Outcome::Applied { id: migration.id, duration }; + } + } + } +} + +async fn run_migration( + db: &Surreal, + table: &str, + migration: &Migration, +) -> Result { + let span = info_span!("migration", id = %migration.id); + + async { + trace!(content = %migration.content, "executing migration"); + + let checksum = checksum::compute(&migration.content); + let t0 = Instant::now(); + + let tx = db.clone().begin().await.context(SurrealSnafu)?; + + let migration_result = tx + .query(&migration.content) + .await + .and_then(|r| r.check()) + .context(MigrationFailedSnafu { + id: migration.id.clone(), + }); + + let duration = t0.elapsed(); + + if let Err(e) = migration_result { + let _ = tx.cancel().await; + return Err(e); + } + + let insert_result = tx + .query( + "CREATE type::record($t, $id) SET name = $name, checksum = $checksum, applied_at \ + = time::now(), duration_ms = $duration_ms", + ) + .bind(("t", table.to_string())) + .bind(("id", migration.id.clone())) + .bind(("name", migration.name.clone())) + .bind(("checksum", checksum)) + .bind(("duration_ms", duration.as_millis() as i64)) + .await + .and_then(|r| r.check()) + .context(MigrationFailedSnafu { + id: migration.id.clone(), + }); + + if let Err(e) = insert_result { + let _ = tx.cancel().await; + return Err(e); + } + + tx.commit().await.context(MigrationFailedSnafu { + id: migration.id.clone(), + })?; + + info!( + id = %migration.id, + duration_ms = duration.as_millis(), + "applied migration" + ); + + Ok(duration) + } + .instrument(span) + .await +} diff --git a/migrations-tool/src/types.rs b/migrations-tool/src/types.rs new file mode 100644 index 0000000..afc7e50 --- /dev/null +++ b/migrations-tool/src/types.rs @@ -0,0 +1,49 @@ +use std::time::Duration; + +/// A single migration to be applied to the database. +#[derive(Debug, Clone)] +pub struct Migration { + /// Unique identifier used for sort order and record lookup. + /// + /// When loaded from files this equals the full filename + /// (e.g. `1779584187_baseline.surql`). + pub id: String, + + /// Human-readable label stored in the state table. + pub name: String, + + /// Raw SurrealQL to execute. + pub content: String, +} + +/// The result of processing a single migration. +#[derive(Debug)] +pub enum Outcome { + /// The migration was executed and committed. + Applied { + /// The migration id. + id: String, + /// Wall-clock time from transaction start to commit. + duration: Duration, + }, + /// The migration was skipped. + Skipped { + /// The migration id. + id: String, + /// Why it was skipped. + reason: SkipReason, + }, +} + +/// Why a migration was not executed. +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum SkipReason { + /// The migration is already recorded in the state table with a matching + /// checksum. + AlreadyApplied, + /// The migration is recorded in the state table but its content has + /// changed. + /// + /// This only occurs when `ignore_checksum_changes(true)` is set. + ChecksumChangedButIgnored, +} diff --git a/migrations-tool/tests/common/mod.rs b/migrations-tool/tests/common/mod.rs new file mode 100644 index 0000000..a3a2a02 --- /dev/null +++ b/migrations-tool/tests/common/mod.rs @@ -0,0 +1,274 @@ +#![allow(dead_code)] + +use futures::StreamExt as _; +use migrations_tool::{Error, Migration, Migrator, Outcome, SkipReason}; +use surrealdb::{Surreal, engine::any::Any}; + +fn m(id: &str, content: &str) -> Migration { + Migration { + id: id.to_string(), + name: id.to_string(), + content: content.to_string(), + } +} + +/// Scenario 1 — empty migration set is a no-op. +pub async fn empty_set(db: &Surreal) { + let plan = Migrator::from_strings(vec![]) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + assert_eq!(plan.pending().len(), 0); + assert_eq!(plan.skipped().len(), 0); + + let results: Vec<_> = plan.execute(db).collect().await; + assert!(results.is_empty()); +} + +/// Scenario 2 — apply 3 migrations and verify state table contents. +pub async fn apply_three(db: &Surreal) { + let migrations = vec![ + m("001_a.surql", "DEFINE TABLE a SCHEMALESS;"), + m("002_b.surql", "DEFINE TABLE b SCHEMALESS;"), + m("003_c.surql", "DEFINE TABLE c SCHEMALESS;"), + ]; + + let plan = Migrator::from_strings(migrations) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + assert_eq!(plan.pending().len(), 3); + + let outcomes: Vec<_> = plan.execute(db).collect().await; + assert_eq!(outcomes.len(), 3); + for o in &outcomes { + assert!(o.is_ok(), "unexpected error: {o:?}"); + } + + // State table must record all three. + let mut resp = db + .query("SELECT meta::id(id) AS id FROM _migrations ORDER BY id ASC") + .await + .unwrap(); + let ids: Vec = resp.take(0).unwrap(); + assert_eq!(ids.len(), 3); +} + +/// Scenario 3 — re-running the same set skips everything. +pub async fn rerun_all_skipped(db: &Surreal) { + let migrations = vec![ + m("001_a.surql", "DEFINE TABLE a SCHEMALESS;"), + m("002_b.surql", "DEFINE TABLE b SCHEMALESS;"), + ]; + + // First run. + let plan = Migrator::from_strings(migrations.clone()) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + let _: Vec<_> = plan.execute(db).collect().await; + + // Second run. + let plan2 = Migrator::from_strings(migrations) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + assert_eq!(plan2.pending().len(), 0); + assert_eq!(plan2.skipped().len(), 2); + for (_, reason) in plan2.skipped() { + assert_eq!(*reason, SkipReason::AlreadyApplied); + } + + let results: Vec<_> = plan2.execute(db).collect().await; + assert!(results.is_empty()); +} + +/// Scenario 4 — modified content with default config → ChecksumMismatch from +/// plan(). +pub async fn checksum_mismatch_error(db: &Surreal) { + // Apply original. + let original = vec![m("001_a.surql", "DEFINE TABLE a SCHEMALESS;")]; + let plan = Migrator::from_strings(original) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + let _: Vec<_> = plan.execute(db).collect().await; + + // Try to plan with modified content. + let modified = vec![m("001_a.surql", "DEFINE TABLE a_modified SCHEMALESS;")]; + let result = Migrator::from_strings(modified) + .validate() + .unwrap() + .plan(db) + .await; + + assert!( + matches!(result, Err(Error::ChecksumMismatch { .. })), + "expected ChecksumMismatch, got: {result:?}" + ); +} + +/// Scenario 5 — modified content with ignore → skip with +/// ChecksumChangedButIgnored. +pub async fn checksum_mismatch_ignored(db: &Surreal) { + // Apply original. + let original = vec![m("001_a.surql", "DEFINE TABLE a SCHEMALESS;")]; + let plan = Migrator::from_strings(original) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + let _: Vec<_> = plan.execute(db).collect().await; + + // Re-plan with modified content and ignore flag set. + let modified = vec![m("001_a.surql", "DEFINE TABLE a_modified SCHEMALESS;")]; + let plan2 = Migrator::from_strings(modified) + .ignore_checksum_changes(true) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + assert_eq!(plan2.pending().len(), 0); + assert_eq!(plan2.skipped().len(), 1); + assert_eq!(plan2.skipped()[0].1, SkipReason::ChecksumChangedButIgnored); +} + +/// Scenario 6 — bad SurrealQL → error, transaction rolled back, no state row +/// written. +pub async fn bad_sql_no_state_row(db: &Surreal) { + let migrations = vec![m("001_bad.surql", "THIS IS NOT VALID SURQL !!!!!")]; + + let plan = Migrator::from_strings(migrations) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + let results: Vec<_> = plan.execute(db).collect().await; + assert_eq!(results.len(), 1); + assert!(results[0].is_err(), "expected error, got: {:?}", results[0]); + + // State table must be empty — transaction rolled back. + let mut resp = db.query("SELECT * FROM _migrations").await.unwrap(); + let rows: Vec = resp.take(0).unwrap(); + assert!( + rows.is_empty(), + "state row was written despite transaction failure" + ); +} + +/// Scenario 7 — duplicate IDs → validation error before any DB call. +pub async fn duplicate_ids(db: &Surreal) { + let migrations = vec![ + m("001.surql", "DEFINE TABLE a SCHEMALESS;"), + m("001.surql", "DEFINE TABLE b SCHEMALESS;"), + ]; + + let result = Migrator::from_strings(migrations).validate(); + assert!( + matches!(result, Err(Error::DuplicateIds { .. })), + "expected DuplicateIds, got: {result:?}" + ); + + // Ensure db was never touched. + let _ = db; // consumed to suppress lint +} + +/// Scenario 8 — file source: lexical sort is correct across different +/// magnitudes. +pub async fn lexical_sort(db: &Surreal, dir: &std::path::Path) { + // Five filenames that span orders of magnitude but sort correctly lexically + // because the prefix is fixed-width. + let files = [ + ("1000000000_first.surql", "DEFINE TABLE first SCHEMALESS;"), + ("1000000001_second.surql", "DEFINE TABLE second SCHEMALESS;"), + ("1000000002_third.surql", "DEFINE TABLE third SCHEMALESS;"), + ("9000000000_fourth.surql", "DEFINE TABLE fourth SCHEMALESS;"), + ("9999999999_fifth.surql", "DEFINE TABLE fifth SCHEMALESS;"), + ]; + + for (name, content) in &files { + std::fs::write(dir.join(name), content).unwrap(); + } + + let plan = Migrator::from_files(dir) + .unwrap() + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + let pending = plan.pending(); + assert_eq!(pending.len(), 5); + assert_eq!(pending[0].id, "1000000000_first.surql"); + assert_eq!(pending[1].id, "1000000001_second.surql"); + assert_eq!(pending[2].id, "1000000002_third.surql"); + assert_eq!(pending[3].id, "9000000000_fourth.surql"); + assert_eq!(pending[4].id, "9999999999_fifth.surql"); +} + +/// Scenario 9 — stream halts on first error; subsequent migrations not +/// attempted. +pub async fn stream_halts_on_error(db: &Surreal) { + let migrations = vec![ + m("001_ok.surql", "DEFINE TABLE ok1 SCHEMALESS;"), + m("002_bad.surql", "THIS IS INVALID SURQL"), + m("003_ok.surql", "DEFINE TABLE ok3 SCHEMALESS;"), + ]; + + let plan = Migrator::from_strings(migrations) + .validate() + .unwrap() + .plan(db) + .await + .unwrap(); + + let results: Vec<_> = plan.execute(db).collect().await; + + // Should be: Ok(001 applied), Err(002 failed). 003 must NOT appear. + assert_eq!( + results.len(), + 2, + "expected 2 results, got {}", + results.len() + ); + assert!(results[0].is_ok(), "first migration should succeed"); + assert!(results[1].is_err(), "second migration should fail"); + + // 003 was not applied. + let mut resp = db + .query("SELECT meta::id(id) AS id FROM _migrations WHERE meta::id(id) = '003_ok.surql'") + .await + .unwrap(); + let rows: Vec = resp.take(0).unwrap(); + assert!( + rows.is_empty(), + "migration 003 should not have been applied" + ); +} + +/// Helper used in outcome assertions. +pub fn outcome_id(outcome: &Outcome) -> &str { + match outcome { + Outcome::Applied { id, .. } => id, + Outcome::Skipped { id, .. } => id, + } +} diff --git a/migrations-tool/tests/mem.rs b/migrations-tool/tests/mem.rs new file mode 100644 index 0000000..d3ff97f --- /dev/null +++ b/migrations-tool/tests/mem.rs @@ -0,0 +1,58 @@ +mod common; + +use surrealdb::engine::any::connect; + +async fn db() -> surrealdb::Surreal { + let db = connect("mem://").await.expect("connect mem://"); + db.use_ns("test") + .use_db("test") + .await + .expect("use_ns/use_db"); + db +} + +#[tokio::test] +async fn empty_set() { + common::empty_set(&db().await).await; +} + +#[tokio::test] +async fn apply_three() { + common::apply_three(&db().await).await; +} + +#[tokio::test] +async fn rerun_all_skipped() { + common::rerun_all_skipped(&db().await).await; +} + +#[tokio::test] +async fn checksum_mismatch_error() { + common::checksum_mismatch_error(&db().await).await; +} + +#[tokio::test] +async fn checksum_mismatch_ignored() { + common::checksum_mismatch_ignored(&db().await).await; +} + +#[tokio::test] +async fn bad_sql_no_state_row() { + common::bad_sql_no_state_row(&db().await).await; +} + +#[tokio::test] +async fn duplicate_ids() { + common::duplicate_ids(&db().await).await; +} + +#[tokio::test] +async fn lexical_sort() { + let dir = tempfile::tempdir().expect("tempdir"); + common::lexical_sort(&db().await, dir.path()).await; +} + +#[tokio::test] +async fn stream_halts_on_error() { + common::stream_halts_on_error(&db().await).await; +} diff --git a/migrations-tool/tests/rocksdb.rs b/migrations-tool/tests/rocksdb.rs new file mode 100644 index 0000000..b7a017a --- /dev/null +++ b/migrations-tool/tests/rocksdb.rs @@ -0,0 +1,71 @@ +mod common; + +use tempfile::TempDir; + +async fn db() -> (surrealdb::Surreal, TempDir) { + let dir = tempfile::tempdir().expect("tempdir for rocksdb"); + let path = format!("rocksdb://{}", dir.path().display()); + let db = surrealdb::engine::any::connect(path) + .await + .expect("connect rocksdb"); + db.use_ns("test") + .use_db("test") + .await + .expect("use_ns/use_db"); + (db, dir) +} + +#[tokio::test] +async fn empty_set() { + let (db, _dir) = db().await; + common::empty_set(&db).await; +} + +#[tokio::test] +async fn apply_three() { + let (db, _dir) = db().await; + common::apply_three(&db).await; +} + +#[tokio::test] +async fn rerun_all_skipped() { + let (db, _dir) = db().await; + common::rerun_all_skipped(&db).await; +} + +#[tokio::test] +async fn checksum_mismatch_error() { + let (db, _dir) = db().await; + common::checksum_mismatch_error(&db).await; +} + +#[tokio::test] +async fn checksum_mismatch_ignored() { + let (db, _dir) = db().await; + common::checksum_mismatch_ignored(&db).await; +} + +#[tokio::test] +async fn bad_sql_no_state_row() { + let (db, _dir) = db().await; + common::bad_sql_no_state_row(&db).await; +} + +#[tokio::test] +async fn duplicate_ids() { + let (db, _dir) = db().await; + common::duplicate_ids(&db).await; +} + +#[tokio::test] +async fn lexical_sort() { + let (db, _db_dir) = db().await; + let mig_dir = tempfile::tempdir().expect("tempdir for migrations"); + common::lexical_sort(&db, mig_dir.path()).await; +} + +#[tokio::test] +async fn stream_halts_on_error() { + let (db, _dir) = db().await; + common::stream_halts_on_error(&db).await; +} diff --git a/migrations/1779584187_baseline_post_v2.surql b/migrations/1779584187_baseline_post_v2.surql new file mode 100644 index 0000000..e2834b9 --- /dev/null +++ b/migrations/1779584187_baseline_post_v2.surql @@ -0,0 +1,159 @@ +-- ------------------------------ +-- TABLE: apps +-- ------------------------------ + +DEFINE TABLE OVERWRITE apps TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE available ON apps TYPE bool DEFAULT true PERMISSIONS FULL; +DEFINE FIELD OVERWRITE banner ON apps TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE default_tags ON apps TYPE set> DEFAULT [] REFERENCE ON DELETE IGNORE PERMISSIONS FULL; +DEFINE FIELD OVERWRITE default_tags.* ON apps TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE description ON apps TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE developer ON apps TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE enabled ON apps TYPE bool PERMISSIONS FULL; +DEFINE FIELD OVERWRITE id ON apps TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE name ON apps TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE tags ON apps TYPE set> DEFAULT [] REFERENCE ON DELETE IGNORE PERMISSIONS FULL; +DEFINE FIELD OVERWRITE tags.* ON apps TYPE record PERMISSIONS FULL; + + + +-- ------------------------------ +-- TABLE: companions +-- ------------------------------ + +DEFINE TABLE OVERWRITE companions TYPE RELATION IN workshop_items OUT workshop_items SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE id ON companions TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE in ON companions TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE note ON companions TYPE none | string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE out ON companions TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE source ON companions TYPE 'system' | record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE status ON companions TYPE -1 | 0 | 1 DEFAULT 0 PERMISSIONS FULL; +DEFINE FIELD OVERWRITE upvote_count ON companions TYPE int DEFAULT 0 PERMISSIONS FULL; +DEFINE FIELD OVERWRITE vote_count ON companions TYPE int DEFAULT 0 PERMISSIONS FULL; + + + +-- ------------------------------ +-- TABLE: item_dependencies +-- ------------------------------ + +DEFINE TABLE OVERWRITE item_dependencies TYPE RELATION IN workshop_items OUT workshop_items SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE in ON item_dependencies TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE out ON item_dependencies TYPE record PERMISSIONS FULL; + +DEFINE INDEX OVERWRITE dep_out ON item_dependencies FIELDS out; + + +-- ------------------------------ +-- TABLE: properties +-- ------------------------------ + +DEFINE TABLE OVERWRITE properties TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE id ON properties TYPE { class: string, value: string } PERMISSIONS FULL; + + +-- ------------------------------ +-- TABLE: tags +-- ------------------------------ + +DEFINE TABLE OVERWRITE tags TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE app_id ON tags TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE display_name ON tags TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE id ON tags TYPE string PERMISSIONS FULL; + +DEFINE INDEX OVERWRITE field_app_id_tag ON tags FIELDS app_id, display_name; + + +-- ------------------------------ +-- TABLE: usernames +-- ------------------------------ + +DEFINE TABLE OVERWRITE usernames TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE last_updated ON usernames TYPE datetime PERMISSIONS FULL; +DEFINE FIELD OVERWRITE name ON usernames TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE username ON usernames TYPE record REFERENCE ON DELETE IGNORE PERMISSIONS FULL; + +DEFINE INDEX OVERWRITE unique_username ON usernames FIELDS username; + + +-- ------------------------------ +-- TABLE: users +-- ------------------------------ + +DEFINE TABLE OVERWRITE users TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE admin ON users TYPE bool PERMISSIONS FULL; +DEFINE FIELD OVERWRITE banned ON users TYPE bool PERMISSIONS FULL; +DEFINE FIELD OVERWRITE id ON users TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE last_logged_in ON users TYPE datetime PERMISSIONS FULL; + + + +-- ------------------------------ +-- TABLE: votes +-- ------------------------------ + +DEFINE TABLE OVERWRITE votes TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE id ON votes TYPE { item: record, link: record | record, user: record } PERMISSIONS FULL; +DEFINE FIELD OVERWRITE score ON votes TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE user ON votes TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE when ON votes TYPE datetime PERMISSIONS FULL; + + + +-- ------------------------------ +-- TABLE: workshop_item_properties +-- ------------------------------ + +DEFINE TABLE OVERWRITE workshop_item_properties TYPE RELATION IN workshop_items OUT properties SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE in ON workshop_item_properties TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE note ON workshop_item_properties TYPE none | string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE out ON workshop_item_properties TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE source ON workshop_item_properties TYPE 'system' | record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE status ON workshop_item_properties TYPE -1 | 0 | 1 DEFAULT 0 PERMISSIONS FULL; +DEFINE FIELD OVERWRITE upvote_count ON workshop_item_properties TYPE int DEFAULT 0 PERMISSIONS FULL; +DEFINE FIELD OVERWRITE vote_count ON workshop_item_properties TYPE int DEFAULT 0 PERMISSIONS FULL; + +DEFINE INDEX OVERWRITE unique_workshop_item_properties ON workshop_item_properties FIELDS in, out UNIQUE; + + +-- ------------------------------ +-- TABLE: workshop_items +-- ------------------------------ + +DEFINE TABLE OVERWRITE workshop_items TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD OVERWRITE appid ON workshop_items TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE author ON workshop_items TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE description ON workshop_items TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE id ON workshop_items TYPE string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE languages ON workshop_items TYPE set PERMISSIONS FULL; +DEFINE FIELD OVERWRITE languages.* ON workshop_items TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE last_updated ON workshop_items TYPE int PERMISSIONS FULL; +DEFINE FIELD OVERWRITE preview_url ON workshop_items TYPE none | string PERMISSIONS FULL; +DEFINE FIELD OVERWRITE score ON workshop_items TYPE float PERMISSIONS FULL; +DEFINE FIELD OVERWRITE tags ON workshop_items TYPE set> PERMISSIONS FULL; +DEFINE FIELD OVERWRITE tags.* ON workshop_items TYPE record PERMISSIONS FULL; +DEFINE FIELD OVERWRITE title ON workshop_items TYPE string PERMISSIONS FULL; + +DEFINE INDEX OVERWRITE item_id ON workshop_items FIELDS id UNIQUE; +DEFINE INDEX OVERWRITE item_language ON workshop_items FIELDS languages; +DEFINE INDEX OVERWRITE item_score ON workshop_items FIELDS score; +DEFINE INDEX OVERWRITE item_title ON workshop_items FIELDS title; +DEFINE INDEX OVERWRITE item_updated ON workshop_items FIELDS last_updated; + +-- Remove old surrealdb-migrations tables +REMOVE TABLE IF EXISTS migration; +REMOVE TABLE IF EXISTS migrations; +REMOVE TABLE IF EXISTS migration_lock; +REMOVE TABLE IF EXISTS migration_state; +REMOVE TABLE IF EXISTS __migrations; +REMOVE TABLE IF EXISTS script_migration; \ No newline at end of file diff --git a/migrations/1780095963382_workshop_items.surql b/migrations/1780095963382_workshop_items.surql new file mode 100644 index 0000000..5e73b9f --- /dev/null +++ b/migrations/1780095963382_workshop_items.surql @@ -0,0 +1,43 @@ +-- Migrate workshop_items +-- id's type has been changed from a string to an int +-- app has been renamed from appid & changed to a record +-- author has been changed to a record + +-- Copy to new table +DEFINE TABLE workshop_items_temp TYPE NORMAL SCHEMALESS PERMISSIONS NONE; +INSERT INTO workshop_items_temp (SELECT *, id.id() AS id FROM workshop_items); + +-- Define new table +REMOVE TABLE workshop_items; +DEFINE TABLE workshop_items TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD id ON workshop_items TYPE int PERMISSIONS FULL; +DEFINE FIELD app ON workshop_items TYPE record PERMISSIONS FULL; +DEFINE FIELD author ON workshop_items TYPE record PERMISSIONS FULL; +DEFINE FIELD description ON workshop_items TYPE string PERMISSIONS FULL; +DEFINE FIELD languages ON workshop_items TYPE set PERMISSIONS FULL; +DEFINE FIELD last_updated ON workshop_items TYPE int PERMISSIONS FULL; +DEFINE FIELD preview_url ON workshop_items TYPE none | string PERMISSIONS FULL; +DEFINE FIELD score ON workshop_items TYPE float PERMISSIONS FULL; +DEFINE FIELD tags ON workshop_items TYPE set> PERMISSIONS FULL; +DEFINE FIELD title ON workshop_items TYPE string PERMISSIONS FULL; + +DEFINE INDEX item_id ON workshop_items FIELDS id UNIQUE; +DEFINE INDEX item_language ON workshop_items FIELDS languages; +DEFINE INDEX item_score ON workshop_items FIELDS score; +DEFINE INDEX item_title ON workshop_items FIELDS title; +DEFINE INDEX item_updated ON workshop_items FIELDS last_updated; + +-- Copy back and mutate +INSERT INTO workshop_items ( + SELECT *, + type::number(id.id()) AS id, + type::record('usernames', type::number(author)) as author, + type::record('apps', type::number(appid)) as app, + type::set(languages) as languages, + type::set(tags) as tags + OMIT appid + FROM workshop_items_temp); + +-- Drop old table +REMOVE TABLE workshop_items_temp; \ No newline at end of file diff --git a/migrations/1780179127495_languages_to_array.surql b/migrations/1780179127495_languages_to_array.surql new file mode 100644 index 0000000..ca5fe00 --- /dev/null +++ b/migrations/1780179127495_languages_to_array.surql @@ -0,0 +1,6 @@ +-- More SurrealDB half assed testing +-- Set == BTreeSet, which, doesn't actually implement SurrealValue so you can't ser/de it... +-- Sorry but that's an asinine oversite + +DEFINE FIELD OVERWRITE languages ON workshop_items TYPE array VALUE $value.distinct() PERMISSIONS FULL; +UPDATE workshop_items SET languages = languages; \ No newline at end of file diff --git a/migrations/1780180300575_tags_to_array.surql b/migrations/1780180300575_tags_to_array.surql new file mode 100644 index 0000000..e901f5a --- /dev/null +++ b/migrations/1780180300575_tags_to_array.surql @@ -0,0 +1,6 @@ +-- More SurrealDB half assed testing +-- Set == BTreeSet, which, doesn't actually implement SurrealValue so you can't ser/de it... +-- Sorry but that's an asinine oversight + +DEFINE FIELD OVERWRITE tags ON workshop_items TYPE array> VALUE $value.distinct() PERMISSIONS FULL; +UPDATE workshop_items SET tags = tags; \ No newline at end of file diff --git a/migrations/1780193282948_workshop_item_properties_in_record.surql b/migrations/1780193282948_workshop_item_properties_in_record.surql new file mode 100644 index 0000000..a461fb8 --- /dev/null +++ b/migrations/1780193282948_workshop_item_properties_in_record.surql @@ -0,0 +1,46 @@ +-- Copy to new table +DEFINE TABLE workshop_item_properties_temp TYPE RELATION SCHEMALESS PERMISSIONS NONE; +FOR $record IN ( + SELECT * + FROM workshop_item_properties +) { + LET $in = $record.in; + LET $out = $record.out; + RELATE $in -> workshop_item_properties_temp -> $out SET + note = $record.note, + source = $record.source, + status = $record.status, + upvote_count = $record.upvote_count, + vote_count = $record.vote_count; +}; + +-- Define new table +REMOVE TABLE workshop_item_properties; +DEFINE TABLE workshop_item_properties TYPE RELATION IN workshop_items OUT properties SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD note ON workshop_item_properties TYPE none | string PERMISSIONS FULL; +DEFINE FIELD source ON workshop_item_properties TYPE 'system' | record PERMISSIONS FULL; +DEFINE FIELD status ON workshop_item_properties TYPE -1 | 0 | 1 DEFAULT 0 PERMISSIONS FULL; +DEFINE FIELD upvote_count ON workshop_item_properties TYPE int DEFAULT 0 PERMISSIONS FULL; +DEFINE FIELD vote_count ON workshop_item_properties TYPE int DEFAULT 0 PERMISSIONS FULL; + +DEFINE INDEX unique_workshop_item_properties ON workshop_item_properties FIELDS in, out UNIQUE; + +-- Copy back and mutate + +FOR $record IN ( + SELECT * + FROM workshop_item_properties_temp +) { + LET $in = type::record("workshop_items", type::number($record.in.id())); + LET $out = $record.out; + RELATE $in -> workshop_item_properties -> $out SET + note = $record.note, + source = $record.source, + status = $record.status, + upvote_count = $record.upvote_count, + vote_count = $record.vote_count; +}; + +-- Drop old table +REMOVE TABLE workshop_item_properties_temp; diff --git a/migrations/1780200655242_item_dependencies.surql b/migrations/1780200655242_item_dependencies.surql new file mode 100644 index 0000000..556d75c --- /dev/null +++ b/migrations/1780200655242_item_dependencies.surql @@ -0,0 +1,32 @@ +-- Migrate the IDs in item dependencies from strings to integers + +-- Copy to new table +DEFINE TABLE item_dependencies_temp TYPE RELATION SCHEMALESS PERMISSIONS NONE; +FOR $record IN ( + SELECT * + FROM item_dependencies +) { + LET $in = $record.in; + LET $out = $record.out; + RELATE $in -> item_dependencies_temp -> $out; +}; + +-- Define new table +REMOVE TABLE item_dependencies; +DEFINE TABLE item_dependencies TYPE RELATION IN workshop_items OUT workshop_items SCHEMAFULL PERMISSIONS NONE; + +DEFINE INDEX dep_out ON item_dependencies FIELDS out; + +-- Copy back and mutate + +FOR $record IN ( + SELECT * + FROM item_dependencies_temp +) { + LET $in = type::record("workshop_items", type::number($record.in.id())); + LET $out = type::record("workshop_items", type::number($record.out.id())); + RELATE $in -> item_dependencies -> $out; +}; + +-- Drop old table +REMOVE TABLE item_dependencies_temp; diff --git a/migrations/1780200670251_usernames.surql b/migrations/1780200670251_usernames.surql new file mode 100644 index 0000000..a4b0ad3 --- /dev/null +++ b/migrations/1780200670251_usernames.surql @@ -0,0 +1,24 @@ +-- Migrate the IDs in usernames from string to int + +-- Copy to new table +DEFINE TABLE usernames_temp TYPE NORMAL SCHEMALESS PERMISSIONS NONE; +INSERT INTO usernames_temp (SELECT *, id.id() AS id FROM usernames); + +-- Define new table +REMOVE TABLE usernames; +DEFINE TABLE usernames TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD id ON usernames TYPE int PERMISSIONS FULL; +DEFINE FIELD last_updated ON usernames TYPE datetime PERMISSIONS FULL; +DEFINE FIELD name ON usernames TYPE string PERMISSIONS FULL; + +DEFINE INDEX unique_username ON usernames FIELDS id UNIQUE; +-- Copy back and mutate +LET $records = (SELECT * FROM usernames_temp); +FOR $record IN $records { + LET $id = type::record("usernames", type::number($record.username.id())); + UPSERT $id SET name = $record.name, last_updated = $record.last_updated; +}; + +-- Drop old table +REMOVE TABLE usernames_temp; \ No newline at end of file diff --git a/migrations/1780200708038_users.surql b/migrations/1780200708038_users.surql new file mode 100644 index 0000000..68e594e --- /dev/null +++ b/migrations/1780200708038_users.surql @@ -0,0 +1,18 @@ +-- Migrate the IDs in users from string to int +-- Copy to new table +DEFINE TABLE users_temp TYPE NORMAL SCHEMALESS PERMISSIONS NONE; +INSERT INTO users_temp (SELECT *, id.id() AS id FROM users); + +-- Define new table +REMOVE TABLE users; +DEFINE TABLE users TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + +DEFINE FIELD id ON users TYPE int PERMISSIONS FULL; +DEFINE FIELD admin ON users TYPE bool PERMISSIONS FULL; +DEFINE FIELD banned ON users TYPE bool PERMISSIONS FULL; +DEFINE FIELD last_logged_in ON users TYPE datetime PERMISSIONS FULL; + +-- Copy back and mutate +INSERT INTO users (SELECT *, type::number(id.id()) AS id FROM users_temp); +-- Drop old table +REMOVE TABLE users_temp; \ No newline at end of file diff --git a/migrations/20250602_135928_setup.surql b/migrations/20250602_135928_setup.surql deleted file mode 100644 index e69de29..0000000 diff --git a/migrations/20250612_150541_users_and_votes.surql b/migrations/20250612_150541_users_and_votes.surql deleted file mode 100644 index 8f51507..0000000 --- a/migrations/20250612_150541_users_and_votes.surql +++ /dev/null @@ -1,86 +0,0 @@ --- ------------------------------ --- TABLE: apps --- ------------------------------ - -DEFINE TABLE OVERWRITE apps TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; - -DEFINE FIELD OVERWRITE id ON apps TYPE int PERMISSIONS FULL; -DEFINE FIELD OVERWRITE available ON apps TYPE bool PERMISSIONS FULL; -DEFINE FIELD OVERWRITE banner ON apps TYPE string PERMISSIONS FULL; -DEFINE FIELD OVERWRITE default_tags ON apps TYPE set> PERMISSIONS FULL; -DEFINE FIELD OVERWRITE default_tags[*] ON apps TYPE record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE description ON apps TYPE string PERMISSIONS FULL; -DEFINE FIELD OVERWRITE developer ON apps TYPE string PERMISSIONS FULL; -DEFINE FIELD OVERWRITE enabled ON apps TYPE bool PERMISSIONS FULL; -DEFINE FIELD OVERWRITE name ON apps TYPE string PERMISSIONS FULL; - - - --- ------------------------------ --- TABLE: companions --- ------------------------------ - -DEFINE TABLE OVERWRITE companions TYPE RELATION IN workshop_items OUT workshop_items SCHEMAFULL PERMISSIONS NONE; - -DEFINE FIELD OVERWRITE id ON companions TYPE int PERMISSIONS FULL; -DEFINE FIELD OVERWRITE in ON companions TYPE record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE note ON companions TYPE option PERMISSIONS FULL; -DEFINE FIELD OVERWRITE out ON companions TYPE record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE source ON companions TYPE 'system' | record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE status ON companions TYPE -1 | 0 | 1 DEFAULT 0 PERMISSIONS FULL; -DEFINE FIELD OVERWRITE upvote_count ON companions TYPE int DEFAULT 0 PERMISSIONS FULL; -DEFINE FIELD OVERWRITE vote_count ON companions TYPE int DEFAULT 0 PERMISSIONS FULL; - - - - --- ------------------------------ --- TABLE: properties --- ------------------------------ - -DEFINE TABLE OVERWRITE properties TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; - -DEFINE FIELD id ON properties TYPE { class: string, value: string } PERMISSIONS FULL; - - - --- ------------------------------ --- TABLE: users --- ------------------------------ - -DEFINE TABLE OVERWRITE users TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; - -DEFINE FIELD OVERWRITE admin ON users TYPE bool PERMISSIONS FULL; -DEFINE FIELD OVERWRITE banned ON users TYPE bool PERMISSIONS FULL; -DEFINE FIELD OVERWRITE id ON users TYPE string PERMISSIONS FULL; -DEFINE FIELD OVERWRITE last_logged_in ON users TYPE datetime PERMISSIONS FULL; - - - --- ------------------------------ --- TABLE: votes --- ------------------------------ - -DEFINE TABLE OVERWRITE votes TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; - -DEFINE FIELD OVERWRITE id ON votes TYPE int PERMISSIONS FULL; -DEFINE FIELD OVERWRITE link ON votes TYPE record | record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE score ON votes TYPE int PERMISSIONS FULL; -DEFINE FIELD OVERWRITE user ON votes TYPE record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE when ON votes TYPE datetime PERMISSIONS FULL; - --- ------------------------------ --- TABLE: workshop_item_properties --- ------------------------------ - -DEFINE TABLE OVERWRITE workshop_item_properties TYPE RELATION IN workshop_items OUT properties SCHEMAFULL PERMISSIONS NONE; - -DEFINE FIELD OVERWRITE in ON workshop_item_properties TYPE record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE note ON workshop_item_properties TYPE option PERMISSIONS FULL; -DEFINE FIELD OVERWRITE out ON workshop_item_properties TYPE record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE source ON workshop_item_properties TYPE 'system' | record PERMISSIONS FULL; -DEFINE FIELD OVERWRITE status ON workshop_item_properties TYPE -1 | 0 | 1 DEFAULT 0 PERMISSIONS FULL; -DEFINE FIELD OVERWRITE upvote_count ON workshop_item_properties TYPE int DEFAULT 0 PERMISSIONS FULL; -DEFINE FIELD OVERWRITE vote_count ON workshop_item_properties TYPE int DEFAULT 0 PERMISSIONS FULL; - -DEFINE INDEX unique_workshop_item_properties ON workshop_item_properties FIELDS in, out UNIQUE; diff --git a/migrations/20250717_120822_missing_migrations.surql b/migrations/20250717_120822_missing_migrations.surql deleted file mode 100644 index 3bd9a35..0000000 --- a/migrations/20250717_120822_missing_migrations.surql +++ /dev/null @@ -1,12 +0,0 @@ -DEFINE TABLE OVERWRITE votes TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; - --- ------------------------------ --- FIELDS --- ------------------------------ - -DEFINE FIELD OVERWRITE id ON votes TYPE { item: record, link: record | record, user: record } PERMISSIONS FULL; -DEFINE FIELD OVERWRITE score ON votes TYPE int PERMISSIONS FULL; -DEFINE FIELD OVERWRITE when ON votes TYPE datetime PERMISSIONS FULL; - -REMOVE FIELD IF EXISTS user ON votes; -REMOVE FIELD IF EXISTS link ON votes; \ No newline at end of file diff --git a/migrations/20251201_105542_add_workshop_item_id_index.surql b/migrations/20251201_105542_add_workshop_item_id_index.surql deleted file mode 100644 index 00b425c..0000000 --- a/migrations/20251201_105542_add_workshop_item_id_index.surql +++ /dev/null @@ -1 +0,0 @@ -DEFINE INDEX item_id ON workshop_items FIELDS id UNIQUE; diff --git a/migrations/definitions/_initial.json b/migrations/definitions/_initial.json deleted file mode 100644 index 8f05fab..0000000 --- a/migrations/definitions/_initial.json +++ /dev/null @@ -1 +0,0 @@ -{"schemas":"DEFINE TABLE OVERWRITE item_dependencies TYPE RELATION IN workshop_items OUT workshop_items SCHEMAFULL PERMISSIONS NONE;\n\nDEFINE FIELD OVERWRITE in ON item_dependencies TYPE record PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE out ON item_dependencies TYPE record PERMISSIONS FULL;\n\nDEFINE INDEX OVERWRITE dep_out ON item_dependencies FIELDS out;\n\nDEFINE TABLE OVERWRITE script_migration SCHEMAFULL\n PERMISSIONS\n FOR select FULL\n FOR create, update, delete NONE;\n\nDEFINE FIELD OVERWRITE script_name ON script_migration TYPE string;\nDEFINE FIELD OVERWRITE executed_at ON script_migration TYPE datetime VALUE time::now() READONLY;\nDEFINE TABLE OVERWRITE tags TYPE NORMAL SCHEMAFULL PERMISSIONS NONE;\n\nDEFINE FIELD OVERWRITE app_id ON tags TYPE int PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE display_name ON tags TYPE string PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE id ON tags TYPE string PERMISSIONS FULL;\n\nDEFINE INDEX IF NOT EXISTS field_app_id_tag ON tags FIELDS app_id, display_name;\nDEFINE TABLE OVERWRITE workshop_items TYPE NORMAL SCHEMAFULL PERMISSIONS NONE;\n\nDEFINE FIELD OVERWRITE appid ON workshop_items TYPE int PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE preview_url ON workshop_items TYPE option PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE id ON workshop_items TYPE string PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE author ON workshop_items TYPE string PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE description ON workshop_items TYPE string PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE languages ON workshop_items TYPE set PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE last_updated ON workshop_items TYPE int PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE tags ON workshop_items TYPE set> PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE tags[*] ON workshop_items TYPE record PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE title ON workshop_items TYPE string PERMISSIONS FULL;\nDEFINE FIELD OVERWRITE score ON workshop_items TYPE float PERMISSIONS FULL;\n\nDEFINE INDEX OVERWRITE item_updated ON workshop_items FIELDS last_updated;\nDEFINE INDEX OVERWRITE item_language ON workshop_items FIELDS languages;\nDEFINE INDEX OVERWRITE item_title ON workshop_items FIELDS title;\nDEFINE INDEX OVERWRITE item_score ON workshop_items FIELDS score;\n","events":""} \ No newline at end of file diff --git a/proc-macros/Cargo.toml b/proc-macros/Cargo.toml new file mode 100644 index 0000000..2691300 --- /dev/null +++ b/proc-macros/Cargo.toml @@ -0,0 +1,18 @@ +[package] +edition.workspace = true +license.workspace = true +name = "proc-macros" +version.workspace = true + +[lib] +proc-macro = true + +[dependencies] +quote.workspace = true +syn.workspace = true + +[dev-dependencies] +salvo.workspace = true +serde.workspace = true +serde_json.workspace = true +surrealdb-types.workspace = true diff --git a/proc-macros/src/lib.rs b/proc-macros/src/lib.rs new file mode 100644 index 0000000..9635471 --- /dev/null +++ b/proc-macros/src/lib.rs @@ -0,0 +1,301 @@ +use proc_macro::TokenStream; +use quote::quote; +use syn::{DeriveInput, Expr, Type, parse::Parser, parse_macro_input}; + +struct DualTypeAttr { + internal_ty: Type, + external_ty: Option, + to_external: Option, + to_internal: Option, + surreal: Vec, +} + +impl syn::parse::Parse for DualTypeAttr { + fn parse(input: syn::parse::ParseStream) -> syn::Result { + let internal_ty: Type = input.parse()?; + let mut external_ty = None; + let mut to_external = None; + let mut to_internal = None; + let mut surreal = Vec::new(); + + if input.peek(syn::Token![,]) { + input.parse::()?; + // If the next token is an identifier followed by '=', it's a keyword argument + if !(input.peek(syn::Ident) && input.peek2(syn::Token![=])) { + // Also check if it's `surreal(...)` + if !input.peek2(syn::token::Paren) { + external_ty = Some(input.parse()?); + if input.peek(syn::Token![,]) { + input.parse::()?; + } + } + } + } + + while !input.is_empty() { + if input.peek(syn::Ident) && input.peek2(syn::Token![=]) { + let ident: syn::Ident = input.parse()?; + input.parse::()?; + let expr: Expr = input.parse()?; + if ident == "to_external" { + to_external = Some(expr); + } else if ident == "to_internal" { + to_internal = Some(expr); + } else { + return Err(syn::Error::new( + ident.span(), + "expected `to_external` or `to_internal`", + )); + } + } else { + let meta: syn::Meta = input.parse()?; + if meta.path().is_ident("surreal") { + surreal.push(meta); + } else { + return Err(syn::Error::new( + meta.path().get_ident().map(|i| i.span()).unwrap_or_else(|| meta.path().segments[0].ident.span()), + "expected `to_external = ...`, `to_internal = ...` or `surreal(...)`", + )); + } + } + + if input.peek(syn::Token![,]) { + input.parse::()?; + } + } + + Ok(DualTypeAttr { + internal_ty, + external_ty, + to_external, + to_internal, + surreal, + }) + } +} + +#[proc_macro_attribute] +pub fn dual_struct(attr_ts: TokenStream, item: TokenStream) -> TokenStream { + let mut input = parse_macro_input!(item as DeriveInput); + let original_ident = input.ident.clone(); + let original_attrs = input.attrs.clone(); + + let fields = match &mut input.data { + syn::Data::Struct(s) => &mut s.fields, + _ => { + return TokenStream::from(quote! { + compile_error!("dual_struct can only be applied to structs"); + }); + } + }; + + let mut internal_fields = Vec::new(); + let mut external_fields = Vec::new(); + let mut from_internal_to_external = Vec::new(); + let mut from_external_to_internal = Vec::new(); + + let mut internal_derives = vec![]; + let mut external_derives = vec![]; + + // Parse the attribute input: #[dual_struct(derive(A, B), internal_derive(C), + // external_derive(D))] + let mut shared_derives = Vec::new(); + + { + let attr_parser = syn::meta::parser(|meta| { + if meta.path.is_ident("derive") { + meta.parse_nested_meta(|meta| { + shared_derives.push(meta.path); + Ok(()) + }) + } else { + Err(meta.error("unsupported attribute")) + } + }); + + if !attr_ts.is_empty() + && let Err(e) = attr_parser.parse(attr_ts) + { + return TokenStream::from(e.to_compile_error()); + } + } + + for d in shared_derives { + internal_derives.push(quote! { #d }); + external_derives.push(quote! { #d }); + } + + // Requirement 6: Specific derives + internal_derives.push(quote! { surrealdb_types::SurrealValue }); + external_derives.push(quote! { salvo::prelude::ToSchema }); + + let mut errors = Vec::new(); + + for field in fields.iter_mut() { + let field_ident = &field.ident; + let mut dual_type = None; + let original_ty = field.ty.clone(); + + // Check for #[dual_type(InternalType, ExternalType, ...)] or + // #[dual_type(Type, ...)] + field.attrs.retain(|attr| { + if attr.path().is_ident("dual_type") { + let parse_res = attr.parse_args::(); + match parse_res { + Ok(dual_attr) => { + let internal_ty = dual_attr.internal_ty; + let external_ty = + dual_attr.external_ty.unwrap_or_else(|| original_ty.clone()); + dual_type = Some(( + internal_ty, + external_ty, + dual_attr.to_external, + dual_attr.to_internal, + dual_attr.surreal, + )); + } + Err(e) => { + errors.push(e); + } + } + false // remove the attribute + } else { + true + } + }); + + // Use a temporary field without the removed attribute + let mut internal_field = field.clone(); + let mut external_field = field.clone(); + + if let Some(( + ref internal_ty, + ref external_ty, + ref to_external, + ref to_internal, + ref surreal_attrs, + )) = dual_type + { + internal_field.ty = internal_ty.clone(); + external_field.ty = external_ty.clone(); + + for attr in surreal_attrs { + internal_field.attrs.push(syn::parse_quote!(#[#attr])); + } + + internal_fields.push(quote! { #internal_field }); + external_fields.push(quote! { #external_field }); + + let to_ext_expr = if let Some(func) = to_external { + quote! { #func(item.#field_ident)? } + } else { + quote! { item.#field_ident.try_into().map_err(|e| { + let err_str = format!("failed to convert field `{}`: {e:?}", stringify!(#field_ident)); + surrealdb_types::Error::thrown(err_str) + })? } + }; + from_internal_to_external.push(quote! { #field_ident: #to_ext_expr }); + + let to_int_expr = if let Some(func) = to_internal { + quote! { #func(item.#field_ident) } + } else { + quote! { item.#field_ident.into() } + }; + from_external_to_internal.push(quote! { #field_ident: #to_int_expr }); + } else { + internal_fields.push(quote! { #field }); + external_fields.push(quote! { #field }); + from_internal_to_external.push(quote! { #field_ident: item.#field_ident }); + from_external_to_internal.push(quote! { #field_ident: item.#field_ident }); + } + } + + let internal_ident = syn::Ident::new( + &format!("Internal{}", original_ident), + original_ident.span(), + ); + let external_ident = syn::Ident::new( + &format!("External{}", original_ident), + original_ident.span(), + ); + let original_name_str = original_ident.to_string(); + + let internal_struct_doc = format!( + "Internal version of [`{}`].\n\n```rust\nstruct {} {{\n {}\n}}\n```", + original_ident, + internal_ident, + internal_fields + .iter() + .map(|f| { + let s = quote!(#f).to_string(); + // Replace #[doc = r" ..."] with /// ... + // This is a naive replacement but should work for most cases in docs + s.replace("# [doc = r\"", "///") + .replace("# [doc = \"", "///") + .replace("\"]", "") + .replace("\"] ", "") + }) + .collect::>() + .join(",\n ") + ); + let external_struct_doc = format!( + "External version of [`{}`].\n\n```rust\nstruct {} {{\n {}\n}}\n```", + original_ident, + external_ident, + external_fields + .iter() + .map(|f| { + let s = quote!(#f).to_string(); + s.replace("# [doc = r\"", "///") + .replace("# [doc = \"", "///") + .replace("\"]", "") + .replace("\"] ", "") + }) + .collect::>() + .join(",\n ") + ); + + if !errors.is_empty() { + let compile_errors = errors.iter().map(|e| e.to_compile_error()); + return TokenStream::from(quote! { + #(#compile_errors)* + }); + } + + let expanded = quote! { + #(#original_attrs)* + #[doc = #internal_struct_doc] + #[derive(#(#internal_derives),*)] + #[serde(rename = #original_name_str)] + pub struct #internal_ident { + #(#internal_fields),* + } + + #(#original_attrs)* + #[doc = #external_struct_doc] + #[derive(#(#external_derives),*)] + #[serde(rename = #original_name_str)] + pub struct #external_ident { + #(#external_fields),* + } + + impl TryFrom<#internal_ident> for #external_ident { + type Error = surrealdb_types::Error; + fn try_from(item: #internal_ident) -> Result { + Ok(Self { + #(#from_internal_to_external),* + }) + } + } + + impl From<#external_ident> for #internal_ident { + fn from(item: #external_ident) -> Self { + Self { + #(#from_external_to_internal),* + } + } + } + }; + + TokenStream::from(expanded) +} diff --git a/proc-macros/tests/integration_test.rs b/proc-macros/tests/integration_test.rs new file mode 100644 index 0000000..53218e3 --- /dev/null +++ b/proc-macros/tests/integration_test.rs @@ -0,0 +1,153 @@ +use proc_macros::dual_struct; +use salvo::{oapi::__private::serde_json, prelude::ToSchema}; +use serde::{Deserialize, Serialize}; +use surrealdb_types::SurrealValue; + +// Mock types to simulate the User's environment +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, SurrealValue, ToSchema)] +#[surreal(transparent)] +pub struct ItemID(i64); +impl From for ItemID { + fn from(v: i64) -> Self { + Self(v) + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, SurrealValue, ToSchema)] +#[surreal(transparent)] +pub struct AppID(i64); +impl From for AppID { + fn from(v: i64) -> Self { + Self(v) + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, SurrealValue)] +pub struct IItemID(surrealdb_types::RecordId); +impl From for IItemID { + fn from(id: ItemID) -> Self { + Self(surrealdb_types::RecordId::new("workshop_items", id.0)) + } +} +impl From for ItemID { + fn from(_id: IItemID) -> Self { + // Simple mock conversion for testing + Self(0) + } +} + +#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, SurrealValue)] +pub struct IAppID(surrealdb_types::RecordId); +impl From for IAppID { + fn from(id: AppID) -> Self { + Self(surrealdb_types::RecordId::new("apps", id.0)) + } +} +impl From for AppID { + fn from(_id: IAppID) -> Self { + Self(0) + } +} + +fn to_external_ids(internal: Vec) -> Result, surrealdb_types::Error> { + Ok(internal.into_iter().map(ItemID::from).collect()) +} + +fn to_internal_ids(external: Vec) -> Vec { + external.into_iter().map(IItemID::from).collect() +} + +/// This is a doc comment for ExampleItem +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug, PartialEq))] +struct ExampleItem { + /// The item's ID + #[dual_type(IItemID)] + pub id: ItemID, + #[dual_type(IAppID)] + pub appid: AppID, // Inferred external as AppID, internal as IAppID + + #[dual_type(Vec, to_external = to_external_ids, to_internal = to_internal_ids)] + pub related_items: Vec, + + // Content information + pub title: String, // The titles name + pub description: String, // HTML encoded description from steam + #[serde(skip_serializing_if = "Option::is_none")] + pub preview_url: Option, + + #[dual_type(Vec, to_external = to_external_ids, to_internal = to_internal_ids, surreal(wrap))] + #[serde(default)] + pub wrapped_items: Vec, +} + +#[test] +fn test_surreal_attr() { + // This test primarily checks that it compiles with the surreal(wrap) attribute + // We can also check if the attribute is present via some reflection or just trust compilation for now + let _item = InternalExampleItem { + id: IItemID(surrealdb_types::RecordId::new("workshop_items", 1)), + appid: IAppID(surrealdb_types::RecordId::new("apps", 1)), + related_items: vec![], + title: "title".to_string(), + description: "desc".to_string(), + preview_url: None, + wrapped_items: vec![], + }; +} + +#[test] +fn test_dual_struct_generation() { + let external = ExternalExampleItem { + id: ItemID(123), + appid: AppID(456), + related_items: vec![ItemID(789), ItemID(101)], + title: "Test Title".to_string(), + description: "Test Description".to_string(), + preview_url: None, + wrapped_items: vec![], + }; + + let internal: InternalExampleItem = external.clone().try_into().unwrap(); + let internal_id: IItemID = internal.id.clone(); + let internal_appid: IAppID = internal.appid.clone(); + assert_eq!(internal.related_items.len(), 2); + let _ = internal.preview_url.clone(); + + // Check fields + // internal.id is IItemID + // internal.appid is IAppID + assert_eq!(internal.title, "Test Title"); + + let external_back: ExternalExampleItem = internal.try_into().expect("Conversion failed"); + assert_eq!(external_back.title, "Test Title"); + assert_eq!(external_back.related_items.len(), 2); + // Conversion back for IDs depends on From impls above +} + +#[test] +fn test_serde_rename() { + let external = ExternalExampleItem { + id: ItemID(123), + appid: AppID(456), + related_items: vec![], + title: "Test Title".to_string(), + description: "Test Description".to_string(), + preview_url: None, + wrapped_items: vec![], + }; + + let json = serde_json::to_string(&external).unwrap(); + // Should be renamed to "ExampleItem" in JSON if used in a map or similar, + // but #[serde(rename = "ExampleItem")] on a struct itself usually affects how + // it's named when it's a field in another struct or when using certain + // formats. Actually, for a top-level struct, it doesn't change the JSON + // unless it's in a container. + + #[derive(Serialize)] + struct Container { + item: ExternalExampleItem, + } + let container = Container { item: external }; + let json = serde_json::to_string(&container).unwrap(); + // This doesn't actually test the rename because "item" is the field name. +} diff --git a/prompts/genres.txt b/prompts/genres.txt index f6a4336..7494a04 100644 --- a/prompts/genres.txt +++ b/prompts/genres.txt @@ -1,20 +1,24 @@ -You are an expert data analyst specializing in video game metadata. Your task is to analyze a list of game modifications (mods) and extract their genres and themes. +You are an expert data analyst specializing in video game metadata. Your task is to analyze a list of game modifications (mods) and extract their narrative, aesthetic, and setting-based genres and themes. ### INSTRUCTIONS: -1. **Identify Genres and Themes:** Carefully analyze the "title" and "description" for each game mod provided. - - **Genre** refers to the *category* or *style* of the game mod (e.g., Fantasy, Sci-Fi, Horror, Realism, Comedy). - - **Theme** refers to the *central idea*, *subject*, or *message* explored (e.g., Survival, Exploration, War, Steampunk, Cyberpunk). -2. **Output Format:** You MUST output a valid JSON object with the following structure: +1. **Identify Genres and Themes:** Carefully analyze the "title" and "description" for each game mod. + * **Genre:** Refers to the **narrative or aesthetic category** of the mod's content (e.g., Fantasy, Sci-Fi, Horror, Realism, Comedy, Historical, Adventure). It describes the *kind of world or story* the mod creates. + * **Theme:** Refers to the **core subject, setting, or narrative focus** of the mod (e.g., Survival, Exploration, War, Steampunk, Cyberpunk, Western, Mystery, Romance). +2. **Exclude Technical & Meta Details:** You must filter out any technical, quality-of-life, or modding framework details. + * **Genres must NOT include:** Simulation (unless referring to a life/narrative simulator), Framework, Library, Utility, Overhaul (if mechanical), etc. + * **Themes must NOT include:** Performance, Bug Fixes, Community, Modding, Upgrades, Compatibility, Graphics, Quality of Life, Gameplay Tweaks, etc. + * Only include genres and themes that describe the mod's fictional content, setting, or narrative purpose. +3. **Output Format:** You MUST output a valid JSON object with the following structure: { "genres": [ "genre1", "genre2", ... ], "themes": [ "theme1", "theme2", ... ] } - - The "genres" array should contain a deduplicated list of all identified genres. - - The "themes" array should contain a deduplicated list of all identified themes. -3. **Output Only JSON:** Do not include any additional text, explanations, or formatting outside the JSON object. Your entire response must be the JSON object only. + * Use clear, standardized terms. Deduplicate all entries within each array. + * If no relevant genres or themes are identified for a category, output an empty array `[]` for it. +4. **Output Only JSON:** Do not include any additional text, explanations, or formatting outside the JSON object. Your entire response must be the JSON object only. ### INPUT DATA: -Here is a game mod with its titles and description: +Here is a game mod with its title and description: TITLE: [TITLE] DESCRIPTION: [DESCRIPTION] \ No newline at end of file diff --git a/scratch/Cargo.toml b/scratch/Cargo.toml new file mode 100644 index 0000000..d8ac3d2 --- /dev/null +++ b/scratch/Cargo.toml @@ -0,0 +1,11 @@ +[package] +edition.workspace = true +license.workspace = true +name = "scratch" +version.workspace = true + +[dependencies] +macros.workspace = true +proc-macros.workspace = true +serde.workspace = true +surrealdb-types.workspace = true diff --git a/scratch/src/lib.rs b/scratch/src/lib.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/scratch/src/lib.rs @@ -0,0 +1 @@ + diff --git a/serde-hack/Cargo.toml b/serde-hack/Cargo.toml index 8c98134..72cac5f 100644 --- a/serde-hack/Cargo.toml +++ b/serde-hack/Cargo.toml @@ -1,8 +1,8 @@ [package] +edition.workspace = true name = "serde-hack" version.workspace = true -edition.workspace = true [dependencies] serde.workspace = true -serde-content.workspace = true \ No newline at end of file +serde-content.workspace = true diff --git a/src/actors.rs b/src/actors.rs index 83e21bd..f3da5b9 100644 --- a/src/actors.rs +++ b/src/actors.rs @@ -8,6 +8,8 @@ use tracing::{Instrument, info_span, instrument}; use crate::{ app_config::Config, db::{ + admin_actor::{AdminActor, AdminArgs}, + apps_actor::{AppsActor, AppsArgs}, item_update_actor::{ItemUpdateActor, ItemUpdateArgs}, properties_actor::{PropertiesActor, PropertiesArgs}, }, @@ -16,7 +18,11 @@ use crate::{ language_actor::{LanguageActor, LanguageArgs}, ml_queue_actor::{MLQueueActor, MLQueueArgs}, }, - steam::steam_download_actor::{SteamDownloadActor, SteamDownloadArgs}, + steam::{ + steam_download_actor::{SteamDownloadActor, SteamDownloadArgs}, + steam_tag_actor::{SteamTagActor, SteamTagArgs}, + steam_user_actor::{SteamUserActor, SteamUserArgs}, + }, web::{ auth::{AuthActor, AuthArgs}, item::{ItemActor, ItemArgs}, @@ -72,12 +78,27 @@ pub async fn spawn(config: &Config, db: &Surreal) -> Result<(), Whatever> { .instrument(info_span!("spawn::ml_queue")) .await .whatever_context("Spawning ML queue actor")?; + + let (steam_user_actor, _) = Actor::spawn( + Some("/steam-user".to_string()), + SteamUserActor, + SteamUserArgs { + steam_token: config.steam.api_token.clone(), + database: db.clone(), + client: reqwest_client.clone(), + }, + ) + .instrument(info_span!("spawn::steam_user")) + .await + .whatever_context("Spawning steam user actor")?; + let (item_update_actor, _) = Actor::spawn( Some("/item_updater".to_string()), ItemUpdateActor {}, ItemUpdateArgs { language_actor, bb_actor, + steam_user_actor: steam_user_actor.clone(), database: db.clone(), ml_queue: config.ml_extraction.then_some(ml_queue_actor), }, @@ -85,37 +106,77 @@ pub async fn spawn(config: &Config, db: &Surreal) -> Result<(), Whatever> { .instrument(info_span!("spawn::item_update")) .await .whatever_context("Spawning item_update actor")?; + let (..) = Actor::spawn( - Some("/auth".to_string()), - AuthActor {}, - AuthArgs { + Some("/admin".to_string()), + AdminActor, + AdminArgs { database: db.clone(), - client: reqwest_client.clone(), - base_url: config.base_url.clone(), - biscuit: config.biscuit.clone(), }, ) - .instrument(info_span!("spawn::auth")) .await - .whatever_context("Spawning auth actor")?; - if config.updater { - let (..) = Actor::spawn( + .whatever_context("Spawning admin actor")?; + + let steam_download_actor = if config.updater { + let (actor, _) = Actor::spawn( Some("/steam-download".to_string()), SteamDownloadActor {}, SteamDownloadArgs { steam_token: config.steam.api_token.clone(), item_processing_actor_ref: item_update_actor, database: db.clone(), - app_id: config.steam.appid, - client: reqwest_client, + client: reqwest_client.clone(), force: config.force_update, }, ) .instrument(info_span!("spawn::steam_download")) .await .whatever_context("Spawning steam download actor")?; + Some(actor) + } else { + None + }; + + if config.updater { + Actor::spawn( + Some("/steam-tag".to_string()), + SteamTagActor, + SteamTagArgs { + database: db.clone(), + client: reqwest_client.clone(), + }, + ) + .instrument(info_span!("spawn::steam_tag")) + .await + .whatever_context("Spawning steam tag actor")?; } + let (..) = Actor::spawn( + Some("/apps".to_string()), + AppsActor, + AppsArgs { + database: db.clone(), + download_actor: steam_download_actor, + }, + ) + .await + .whatever_context("Spawning apps actor")?; + + let (..) = Actor::spawn( + Some("/auth".to_string()), + AuthActor {}, + AuthArgs { + database: db.clone(), + client: reqwest_client.clone(), + base_url: config.base_url.clone(), + biscuit: config.biscuit.clone(), + steam_user_actor_ref: steam_user_actor, + }, + ) + .instrument(info_span!("spawn::auth")) + .await + .whatever_context("Spawning auth actor")?; + let (..) = Actor::spawn( Some("/item".to_string()), ItemActor, diff --git a/src/app_config.rs b/src/app_config.rs index 3fc1d98..bcf7918 100644 --- a/src/app_config.rs +++ b/src/app_config.rs @@ -13,12 +13,12 @@ pub struct Config { pub force_update: bool, pub base_url: Arc, pub biscuit: Arc, + pub admin_users: Vec, } #[derive(Deserialize, Redact)] pub struct Steam { #[redact] pub api_token: Arc, - pub appid: u32, } #[derive(Deserialize, Redact)] pub struct Database { @@ -31,7 +31,6 @@ pub struct Database { #[redact(all)] pub struct BiscuitConfig { pub private_key: PrivateKey, - // pub lifetime: Duration, } impl<'de> serde::Deserialize<'de> for BiscuitConfig { diff --git a/src/application/admin_service.rs b/src/application/admin_service.rs new file mode 100644 index 0000000..1e07692 --- /dev/null +++ b/src/application/admin_service.rs @@ -0,0 +1,40 @@ +use crate::{ + db::model::{InternalUser, InternalWorkshopItemProperties}, + domain::admin::{AdminError, AdminPort, PatchRelationshipData, PatchUserData}, +}; + +pub struct AdminService { + repo: R, +} + +impl AdminService { + pub fn new(repo: R) -> Self { + Self { repo } + } + + pub async fn list_users(&self) -> Result, AdminError> { + self.repo.list_users().await + } + + pub async fn patch_user(&self, patch: PatchUserData) -> Result<(), AdminError> { + if patch.admin.is_none() && patch.banned.is_none() { + return Err(AdminError::BadRequest { + msg: "Must set at least one of 'admin' or 'banned'".into(), + }); + } + self.repo.patch_user(patch).await + } + + pub async fn list_workshop_item_properties( + &self, + ) -> Result, AdminError> { + self.repo.list_workshop_item_properties().await + } + + pub async fn patch_workshop_item_property( + &self, + patch: PatchRelationshipData, + ) -> Result<(), AdminError> { + self.repo.patch_workshop_item_property(patch).await + } +} diff --git a/src/application/apps_service.rs b/src/application/apps_service.rs new file mode 100644 index 0000000..a68ac2f --- /dev/null +++ b/src/application/apps_service.rs @@ -0,0 +1,34 @@ +use crate::{ + db::{IAppID, model::InternalApp}, + domain::apps::{AppError, AppsPort}, +}; + +pub struct AppsService { + repo: R, +} + +impl AppsService { + pub fn new(repo: R) -> Self { + Self { repo } + } + + pub async fn list_available(&self) -> Result, AppError> { + self.repo.list_available().await + } + + pub async fn upsert(&self, app: InternalApp) -> Result<(), AppError> { + self.repo.upsert(app).await + } + + pub async fn remove(&self, id: IAppID) -> Result<(), AppError> { + self.repo.remove(id).await + } + + pub async fn list(&self) -> Result, AppError> { + self.repo.list().await + } + + pub async fn get(&self, id: IAppID) -> Result { + self.repo.get(id).await + } +} diff --git a/src/application/mod.rs b/src/application/mod.rs index ecf46a3..2b6f7d7 100644 --- a/src/application/mod.rs +++ b/src/application/mod.rs @@ -1 +1,5 @@ +pub mod admin_service; +pub mod apps_service; pub mod properties_service; +pub mod tags_service; +pub mod user_names_service; diff --git a/src/application/properties_service.rs b/src/application/properties_service.rs index f34ec33..b2ee2bc 100644 --- a/src/application/properties_service.rs +++ b/src/application/properties_service.rs @@ -1,6 +1,9 @@ use crate::{ - db::model::{Source, Status}, - domain::properties::{NewProperty, PropertiesError, PropertiesPort, VoteData}, + db::{ + IUserID, + model::{InternalSource, Status}, + }, + domain::properties::{InternalNewProperty, InternalVoteData, PropertiesError, PropertiesPort}, }; pub struct PropertiesService { @@ -14,8 +17,8 @@ impl PropertiesService { pub async fn new_property( &self, - mut new_property: NewProperty, - source: Source, + mut new_property: InternalNewProperty, + source: InternalSource, status: Status, ) -> Result<(), PropertiesError> { new_property.value = new_property.value.to_ascii_lowercase(); @@ -47,14 +50,22 @@ impl PropertiesService { .await } - pub async fn vote(&self, vote: VoteData, userid: String) -> Result<(), PropertiesError> { + pub async fn vote( + &self, + vote: InternalVoteData, + userid: IUserID, + ) -> Result<(), PropertiesError> { if vote.score != 1 && vote.score != -1 { return Err(PropertiesError::InvalidVoteScore); } self.repo.vote(vote, userid).await } - pub async fn remove_vote(&self, vote: VoteData, userid: String) -> Result<(), PropertiesError> { + pub async fn remove_vote( + &self, + vote: InternalVoteData, + userid: IUserID, + ) -> Result<(), PropertiesError> { self.repo.remove_vote(vote, userid).await } } diff --git a/src/application/tags_service.rs b/src/application/tags_service.rs new file mode 100644 index 0000000..22aca4b --- /dev/null +++ b/src/application/tags_service.rs @@ -0,0 +1,18 @@ +use crate::{ + db::{IAppID, model::InternalTag}, + domain::tags::{TagError, TagsPort}, +}; + +pub struct TagsService { + repo: R, +} + +impl TagsService { + pub fn new(repo: R) -> Self { + Self { repo } + } + + pub async fn update_tags(&self, app: IAppID, tags: Vec) -> Result<(), TagError> { + self.repo.upsert_tags(app, tags).await + } +} diff --git a/src/application/user_names_service.rs b/src/application/user_names_service.rs new file mode 100644 index 0000000..2409498 --- /dev/null +++ b/src/application/user_names_service.rs @@ -0,0 +1,50 @@ +use chrono::{Duration, Utc}; +use tracing::debug; + +use crate::{ + db::IUsernameID, + domain::user_names::{UserName, UserNameError, UserNamesPort}, +}; + +pub struct UserNamesService { + repo: R, +} + +impl UserNamesService { + pub fn new(repo: R) -> Self { + Self { repo } + } + + pub async fn update_user_name( + &self, + id: IUsernameID, + name: String, + ) -> Result<(), UserNameError> { + if match self.repo.get_by_id(id.clone()).await? { + Some(existing) => { + Utc::now().signed_duration_since(existing.last_updated) > Duration::weeks(1) + } + None => true, + } { + debug!(?id, %name, "Upserting username"); + self.repo + .upsert(UserName { + id, + last_updated: Utc::now(), + name, + }) + .await?; + } + + Ok(()) + } + + pub async fn should_update_user(&self, id: IUsernameID) -> Result { + match self.repo.get_by_id(id).await? { + Some(existing) => { + Ok(Utc::now().signed_duration_since(existing.last_updated) > Duration::weeks(1)) + } + None => Ok(true), + } + } +} diff --git a/src/apps.rs b/src/apps.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/src/apps.rs @@ -0,0 +1 @@ + diff --git a/src/db/admin_actor.rs b/src/db/admin_actor.rs new file mode 100644 index 0000000..6ec0389 --- /dev/null +++ b/src/db/admin_actor.rs @@ -0,0 +1,79 @@ +use std::sync::OnceLock; + +use ractor::{Actor, ActorProcessingErr, ActorRef, RpcReplyPort, async_trait}; +use surrealdb::{Surreal, engine::local::Db}; + +use crate::{ + application::admin_service::AdminService, + db::{ + admin_repository::AdminSilo, + model::{InternalUser, InternalWorkshopItemProperties}, + }, + domain::admin::{AdminError, PatchRelationshipData, PatchUserData}, +}; + +pub static ADMIN_ACTOR: OnceLock> = OnceLock::new(); + +pub struct AdminActor; + +pub struct AdminArgs { + pub database: Surreal, +} + +pub struct AdminState { + service: AdminService, +} + +pub enum AdminMsg { + ListUsers(RpcReplyPort, AdminError>>), + PatchUser(PatchUserData, RpcReplyPort>), + ListWorkshopItemProperties( + RpcReplyPort, AdminError>>, + ), + PatchWorkshopItemProperty(PatchRelationshipData, RpcReplyPort>), +} + +#[async_trait] +impl Actor for AdminActor { + type Arguments = AdminArgs; + type Msg = AdminMsg; + type State = AdminState; + + async fn pre_start( + &self, + myself: ActorRef, + args: Self::Arguments, + ) -> Result { + ADMIN_ACTOR.get_or_init(|| myself); + Ok(AdminState { + service: AdminService::new(AdminSilo::new(args.database)), + }) + } + + async fn handle( + &self, + _: ActorRef, + message: Self::Msg, + state: &mut Self::State, + ) -> Result<(), ActorProcessingErr> { + match message { + AdminMsg::ListUsers(reply) => { + let res = state.service.list_users().await; + let _ = reply.send(res); + } + AdminMsg::PatchUser(patch, reply) => { + let res = state.service.patch_user(patch).await; + let _ = reply.send(res); + } + AdminMsg::ListWorkshopItemProperties(reply) => { + let res = state.service.list_workshop_item_properties().await; + let _ = reply.send(res); + } + AdminMsg::PatchWorkshopItemProperty(patch, reply) => { + let res = state.service.patch_workshop_item_property(patch).await; + let _ = reply.send(res); + } + } + Ok(()) + } +} diff --git a/src/db/admin_repository.rs b/src/db/admin_repository.rs new file mode 100644 index 0000000..0285f3e --- /dev/null +++ b/src/db/admin_repository.rs @@ -0,0 +1,103 @@ +use surrealdb::{Surreal, engine::local::Db}; +use tracing::error; + +use crate::{ + db::model::{InternalUser, InternalWorkshopItemProperties}, + domain::admin::{AdminError, AdminPort, PatchRelationshipData, PatchUserData}, +}; + +pub struct AdminSilo { + pub db: Surreal, +} + +impl AdminSilo { + pub fn new(db: Surreal) -> Self { + Self { db } + } +} + +impl AdminPort for AdminSilo { + async fn list_users(&self) -> Result, AdminError> { + match self + .db + .query("SELECT id.id().to_string() as id, * FROM users") + .await + .map(|mut q| q.take(0)) + { + Ok(Ok(results)) => Ok(results), + Ok(Err(e)) | Err(e) => { + error!(?e, "failed to list users"); + Err(AdminError::Internal) + } + } + } + + async fn patch_user(&self, patch: PatchUserData) -> Result<(), AdminError> { + if let Some(banned) = patch.banned + && let Err(e) = self + .db + .query("UPDATE $user SET banned=$banned") + .bind(("user", patch.id.clone())) + .bind(("banned", banned)) + .await + { + error!(?e, "failed to update banned flag"); + return Err(AdminError::Internal); + } + if let Some(admin) = patch.admin + && let Err(e) = self + .db + .query("UPDATE $user SET admin=$admin") + .bind(("user", patch.id)) + .bind(("admin", admin)) + .await + { + error!(?e, "failed to update admin flag"); + return Err(AdminError::Internal); + } + Ok(()) + } + + async fn list_workshop_item_properties( + &self, + ) -> Result, AdminError> { + match self + .db + .query( + "SELECT record::id(in) as in, out.*.id.{class,value} as out, source.to_string(), \ + id.to_string(), * FROM workshop_item_properties", + ) + .await + .map(|mut q| q.take(0)) + { + Ok(Ok(results)) => Ok(results), + Ok(Err(e)) | Err(e) => { + error!(?e, "failed to list workshop item properties"); + Err(AdminError::Internal) + } + } + } + + async fn patch_workshop_item_property( + &self, + patch: PatchRelationshipData, + ) -> Result<(), AdminError> { + let res = self + .db + .query("LET $link = properties:{class: $class, value: $value}") + .query( + "UPDATE ONLY workshop_item_properties SET status=$status WHERE in = $item AND out \ + = $link;", + ) + .bind(("class", patch.property.class)) + .bind(("value", patch.property.value)) + .bind(("item", patch.item)) + .bind(("status", patch.status)) + .await; + if let Err(e) = res { + error!(?e, "failed to patch workshop item property"); + return Err(AdminError::Internal); + } + Ok(()) + } +} diff --git a/src/db/apps_actor.rs b/src/db/apps_actor.rs new file mode 100644 index 0000000..f51e3a5 --- /dev/null +++ b/src/db/apps_actor.rs @@ -0,0 +1,89 @@ +use std::sync::OnceLock; + +use ractor::{Actor, ActorProcessingErr, ActorRef, RpcReplyPort, async_trait}; +use surrealdb::{Surreal, engine::local::Db}; + +use crate::{ + application::apps_service::AppsService, + db::{IAppID, apps_repository::AppsSilo, model::InternalApp}, + domain::apps::AppError, + steam::steam_download_actor::SteamDownloadMsg, +}; + +pub static APPS_ACTOR: OnceLock> = OnceLock::new(); + +pub struct AppsActor; + +pub struct AppsArgs { + pub database: Surreal, + pub download_actor: Option>, +} + +pub struct AppsState { + service: AppsService, + download_actor: Option>, +} + +pub enum AppsMsg { + ListAvailable(RpcReplyPort, AppError>>), + Upsert(InternalApp, RpcReplyPort>), + Remove(IAppID, RpcReplyPort>), + List(RpcReplyPort, AppError>>), + Get(IAppID, RpcReplyPort>), +} + +#[async_trait] +impl Actor for AppsActor { + type Arguments = AppsArgs; + type Msg = AppsMsg; + type State = AppsState; + + async fn pre_start( + &self, + myself: ActorRef, + args: Self::Arguments, + ) -> Result { + APPS_ACTOR.get_or_init(|| myself); + Ok(AppsState { + service: AppsService::new(AppsSilo::new(args.database)), + download_actor: args.download_actor, + }) + } + + async fn handle( + &self, + _: ActorRef, + message: Self::Msg, + state: &mut Self::State, + ) -> Result<(), ActorProcessingErr> { + match message { + AppsMsg::ListAvailable(reply) => { + let _ = reply.send(state.service.list_available().await); + } + AppsMsg::Upsert(app, reply) => { + let app_id = app.id.clone(); + let res = state.service.upsert(app).await; + if let Some(download_actor) = &state.download_actor { + let _ = download_actor.send_message(SteamDownloadMsg::AddApp(app_id)); + } + let _ = reply.send(res); + } + AppsMsg::Remove(id, reply) => { + let res = state.service.remove(id.clone()).await; + if res.is_ok() + && let Some(download_actor) = &state.download_actor + { + let _ = download_actor.send_message(SteamDownloadMsg::RemoveApp(id)); + } + let _ = reply.send(res); + } + AppsMsg::List(reply) => { + let _ = reply.send(state.service.list().await); + } + AppsMsg::Get(id, reply) => { + let _ = reply.send(state.service.get(id).await); + } + } + Ok(()) + } +} diff --git a/src/db/apps_repository.rs b/src/db/apps_repository.rs new file mode 100644 index 0000000..5220bed --- /dev/null +++ b/src/db/apps_repository.rs @@ -0,0 +1,104 @@ +use surrealdb::{IndexedResults, Surreal, engine::local::Db}; +use tracing::{debug, error}; + +use crate::{ + db::{IAppID, model::InternalApp}, + domain::apps::{AppError, AppsPort}, +}; + +pub struct AppsSilo { + pub db: Surreal, +} + +impl AppsSilo { + pub fn new(db: Surreal) -> Self { + Self { db } + } +} + +impl AppsPort for AppsSilo { + async fn list_available(&self) -> Result, AppError> { + match self + .db + .query( + // ToDo: Fix this after migrating the app_id to a record link from an int, also, + // funny bug, [] as tags doesn't return a blank array sometimes + "SELECT available, banner, description, developer, enabled, id, name, [] as tags, \ + [] as default_tags FROM apps WHERE available = true", + ) + .await + .map(|mut q| q.take(0)) + { + Ok(Ok(results)) => Ok(results), + Ok(Err(error)) | Err(error) => { + error!(?error, "failed to list available apps"); + Err(AppError::Internal) + } + } + } + + async fn upsert(&self, app: InternalApp) -> Result<(), AppError> { + match self + .db + .query("UPSERT apps CONTENT $app") + .bind(("app", app.clone())) + .await + .map(IndexedResults::check) + { + Ok(Ok(response)) => { + debug!(?app, ?response, "upserted app"); + Ok(()) + } + Err(error) | Ok(Err(error)) => { + error!(?error, "failed to upsert app"); + Err(AppError::Internal) + } + } + } + + async fn remove(&self, id: IAppID) -> Result<(), AppError> { + if let Err(error) = self.db.query("DELETE $id").bind(("id", id)).await { + error!(?error, "failed to remove app"); + return Err(AppError::Internal); + } + Ok(()) + } + + async fn list(&self) -> Result, AppError> { + match self + .db + .query( + "SELECT available, banner, description, developer, enabled, id, name, [] as tags, \ + [] as default_tags FROM apps", + ) + .await + .map(|mut q| q.take(0)) + { + Ok(Ok(results)) => Ok(results), + Ok(Err(e)) | Err(e) => { + error!(?e, "failed to list apps"); + Err(AppError::Internal) + } + } + } + + async fn get(&self, id: IAppID) -> Result { + match self + .db + .query( + "SELECT available, banner, description, developer, enabled, id, name, [] as tags, \ + [] as default_tags FROM $id", + ) + .bind(("id", id)) + .await + .map(|mut q| q.take(0)) + { + Ok(Ok(Some(app))) => Ok(app), + Ok(Ok(None)) => Err(AppError::NotFound), + Ok(Err(error)) | Err(error) => { + error!(?error, "failed to get app"); + Err(AppError::Internal) + } + } + } +} diff --git a/src/db/item_update_actor.rs b/src/db/item_update_actor.rs index ad62cd7..662d672 100644 --- a/src/db/item_update_actor.rs +++ b/src/db/item_update_actor.rs @@ -1,25 +1,29 @@ use ractor::{Actor, ActorProcessingErr, ActorRef, async_trait}; use snafu::{ResultExt, Whatever}; -use surrealdb::{ - RecordId, Surreal, - engine::local::Db, - sql::{ - Data, Value, - statements::{InsertStatement, UpsertStatement}, - to_value, - }, +use surrealdb::{Surreal, engine::local::Db}; +use surrealdb_core::sql::{ + Expr, + data::Data, + statements::{InsertStatement, UpsertStatement}, }; +use surrealdb_types::{SurrealValue, Value}; use tracing::{debug, error}; use crate::{ - db::model::{Dependencies, WorkshopItem}, + db::{ + IItemID, + model::{Dependencies, InternalWorkshopItem}, + }, processing::{ bb_actor::BBMsg, join_process_actor::{JoinProcessActor, JoinProcessArgs, JoinProcessMsg}, language_actor::{DetectedLanguage, LanguageMsg}, ml_queue_actor::MLQueueMsg, }, - steam::model::{Child, IPublishedResponse, IPublishedStruct, SteamRoot}, + steam::{ + model::{Child, IPublishedResponse, IPublishedStruct, SteamRoot}, + steam_user_actor::SteamUserMsg, + }, }; pub struct ItemUpdateActor {} @@ -27,12 +31,14 @@ pub struct ItemUpdateActor {} pub struct ItemUpdateArgs { pub language_actor: ActorRef, pub bb_actor: ActorRef, + pub steam_user_actor: ActorRef, pub database: Surreal, pub ml_queue: Option>, // optional ML queue actor } pub struct ItemUpdateState { language_actor: ActorRef, bb_actor: ActorRef, + steam_user_actor: ActorRef, database: Surreal, ml_queue: Option>, } @@ -40,8 +46,8 @@ pub struct ItemUpdateState { pub enum ItemUpdateMsg { DeserializeRawFiles(SteamRoot), MainlineProcessing(IPublishedStruct), - Upsert((WorkshopItem, Vec)), - MaybeQueueMl((WorkshopItem, Vec)), + Upsert((InternalWorkshopItem, Vec)), + MaybeQueueMl((InternalWorkshopItem, Vec)), } #[async_trait] impl Actor for ItemUpdateActor { @@ -58,6 +64,7 @@ impl Actor for ItemUpdateActor { database: args.database, language_actor: args.language_actor, bb_actor: args.bb_actor, + steam_user_actor: args.steam_user_actor, ml_queue: args.ml_queue, }) } @@ -99,7 +106,7 @@ impl Actor for ItemUpdateActor { if let Err(error) = maybe_queue_ml(&state.database, state.ml_queue.as_ref(), &item).await { - error!(?error, id = %item.id, "queuing ML work (message)"); + error!(?error, id = ?item.id, "queuing ML work (message)"); } if myself .send_message(ItemUpdateMsg::Upsert((item, children))) @@ -111,8 +118,14 @@ impl Actor for ItemUpdateActor { ItemUpdateMsg::Upsert((item, children)) => { let title = item.title.clone(); let item_id = item.id.clone(); + + // ToDo: Update this, considerations around the ID kind needed + // let _ = state + // .steam_user_actor + // .send_message(SteamUserMsg::Fetch(item.author.into())); + if let Err(error) = insert_data(&state.database, item, children).await { - error!(?error, title, %item_id, "upserting item"); + error!(?error, title, ?item_id, "upserting item"); } } } @@ -133,7 +146,7 @@ impl Actor for ItemUpdateActor { async fn maybe_queue_ml( db: &Surreal, ml_queue: Option<&ActorRef>, - item: &WorkshopItem, + item: &InternalWorkshopItem, ) -> crate::Result<(), Whatever> { if let Some(queue) = ml_queue { let mut resp = db @@ -165,63 +178,53 @@ async fn maybe_queue_ml( async fn insert_data( db: &Surreal, - mut item: WorkshopItem, + mut item: InternalWorkshopItem, children: Vec, ) -> crate::Result<(), Whatever> { let tags = std::mem::take(&mut item.tags); let id = item.id.clone(); - let insert_tags = { - let mut stmt = InsertStatement::default(); - stmt.into = Some(Value::Table("tags".into())); - stmt.data = Data::SingleExpression(to_value(tags.clone()).unwrap()); - stmt.ignore = true; - stmt - }; let insert_item_deps = { - let mut stmt = InsertStatement::default(); - stmt.relation = true; + let mut stmt = InsertStatement { + relation: true, + into: Some(Expr::Table("item_dependencies".into())), + ..Default::default() + }; - stmt.into = Some(Value::Table("item_dependencies".into())); + stmt.into = Some(Expr::Table("item_dependencies".into())); let data = children .into_iter() .map(|child| { - let dep_id = RecordId::from_table_key("workshop_items", child.publishedfileid); - to_value(Dependencies { - id: RecordId::from_table_key( - "item_dependencies", - vec![item.id.clone().into(), dep_id.clone().into()], - ), + let dep_id = IItemID::from(child.publishedfileid); + Dependencies { + id: vec![item.id.clone(), dep_id.clone()], this: item.id.clone(), dependency: dep_id, - }) - .unwrap() + } }) .collect::>(); - stmt.data = Data::SingleExpression(Value::Array(data.into())); + stmt.data = Data::SingleExpression(Expr::from_public_value(Value::Array(data.into()))); stmt.ignore = true; stmt }; - let upsert_item = { - let mut stmt = UpsertStatement::default(); - stmt.data = Some(Data::ReplaceExpression(to_value(item.clone()).unwrap())); - stmt.what = vec![Value::Table("workshop_items".into())].into(); - stmt + let upsert_item = UpsertStatement { + data: Some(Data::ReplaceExpression(Expr::from_public_value( + item.clone().into_value(), + ))), + what: vec![Expr::Table("workshop_items".into())], + ..Default::default() }; let query = db .query("BEGIN TRANSACTION") - .query(insert_tags) - .query(upsert_item.to_string()) // Missing impl for into query + .query(upsert_item) // Missing impl for into query .query(insert_item_deps) .query("UPDATE $id SET tags=$tags") .bind(("id", id)) .bind(( "tags", - tags.iter() - .map(|tag| RecordId::from_table_key("tags", tag.tag.clone())) - .collect::>(), + tags.into_iter().map(|tag| tag.id).collect::>(), )) .query("COMMIT"); let sql = format!("{query:#?}"); diff --git a/src/db/mod.rs b/src/db/mod.rs index 1d9cc5b..38f133d 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,9 +1,112 @@ +pub mod admin_actor; +pub mod admin_repository; +pub mod apps_actor; +pub mod apps_repository; pub mod item_update_actor; pub mod model; pub mod properties_actor; pub mod properties_repository; +pub mod tags_repository; +pub mod user_names_repository; use macros::define_id; +use surrealdb_types::SurrealValue; +use crate::db::model::Property; -define_id!("users", UserID, String); -define_id!("workshop_items", ItemID, String); +define_id!("users", IUserID, UserID, i64); +define_id!("workshop_items", IItemID, ItemID, i64); +define_id!("apps", IAppID, AppID, i64); +define_id!("tags", ITagID, TagID, String); +define_id!("usernames", IUsernameID, UsernameID, i64); +define_id!("properties", IPropertyID, PropertyID, Property); +define_id!("votes", IVoteID, VoteID, String); + +#[cfg(test)] +mod test { + use surrealdb::{Surreal, engine::local::Mem}; + + use crate::db::*; + + #[test] + fn test_type_conversion() { + use std::convert::TryInto; + + use surrealdb_types::RecordId; + + fn test_id(table: &str, key: T) + where + I: From + TryInto + Into + Clone, + E: From + Into + Clone + std::fmt::Debug + PartialEq, + T: Clone + PartialEq + std::fmt::Debug, + >::Error: std::fmt::Debug, + { + let external = E::from(key.clone()); + let internal: I = I::from(external.clone()); + let record_id: RecordId = internal.clone().into(); + + assert_eq!(record_id.table(), table); + // key equality check depends on how it's stored, but we can check conversion + // back + let external_back: E = internal.try_into().unwrap(); + assert_eq!(external, external_back); + } + + test_id::("users", "alice".to_string()); + test_id::("workshop_items", "item1".to_string()); + test_id::("apps", 123); + test_id::("tags", "rpg".to_string()); + test_id::("usernames", 456); + test_id::("properties", "prop1".to_string()); + test_id::("votes", "vote1".to_string()); + // test_id::("companions", + // "comp1".to_string()); + + // For complex IDs, manual check + let key = vec![ + surrealdb_types::Value::from("a"), + surrealdb_types::Value::from("b"), + ]; + let external = ItemDependencyID::from(key.clone()); + let internal = IItemDependencyID::from(external.clone()); + let external_back: ItemDependencyID = internal.try_into().unwrap(); + let key_back: Vec = external_back.into(); + assert_eq!(key, key_back); + + let external_prop = WorkshopItemPropertyID::from(key.clone()); + let internal_prop = IWorkshopItemPropertyID::from(external_prop.clone()); + let external_prop_back: WorkshopItemPropertyID = internal_prop.try_into().unwrap(); + let key_prop_back: Vec = external_prop_back.into(); + assert_eq!(key, key_prop_back); + } + + #[tokio::test] + async fn test_throw() { + let db = Surreal::new::(()).await.unwrap(); + db.use_ns("test").use_db("test").await.unwrap(); + let output = db + .query("DEFINE TABLE OVERWRITE properties TYPE NORMAL SCHEMAFULL PERMISSIONS NONE;") + .query("CREATE properties:ShouldExist;") + .query("BEGIN TRANSACTION;") + .query("CREATE properties:NotExist;") + .query("IF true{THROW \"GRACEFUL\"};") + .query("SELECT * FROM properties;") + .await + .unwrap(); + dbg!(output.check().unwrap()); + } + + #[tokio::test] + async fn test_throw_commit() { + let db = Surreal::new::(()).await.unwrap(); + db.use_ns("test").use_db("test").await.unwrap(); + let query = r#"BEGIN; + LET $person = CREATE ONLY person SET age = rand::int(1,5); + IF $person.age == 5 { + THROW "Whoops"; + }; + CREATE person; + COMMIT;"#; + let output = db.query(query).await.unwrap(); + dbg!(output.check().unwrap()); + } +} diff --git a/src/db/model.rs b/src/db/model.rs index 2c65a1b..3ea54a7 100644 --- a/src/db/model.rs +++ b/src/db/model.rs @@ -1,24 +1,27 @@ use std::{ fmt::{Display, Formatter}, - ops::{Deref, DerefMut}, }; use chrono::{DateTime, Utc}; +use macros::dual_struct; use salvo::prelude::ToSchema; -use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error}; +use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer}; use serde_content::{Value, ValueVisitor}; use serde_hack::ValueRefDeserializer; use serde_repr::{Deserialize_repr, Serialize_repr}; -use surrealdb::{RecordId, RecordIdKey}; +use surrealdb_types::{Object, RecordIdKey, SurrealValue}; +use tracing::error; + +use crate::{ + db::{AppID, IAppID, IItemID, ITagID, IUserID, ItemID, TagID, UserID}, + processing::language_actor::DetectedLanguage, +}; -use crate::processing::language_actor::DetectedLanguage; #[derive(Serialize, Deserialize, Clone, Debug, ToSchema, Default)] pub enum OrderBy { Alphabetical, #[default] LastUpdated, - Score, - Dependents, } impl OrderBy { @@ -26,8 +29,6 @@ impl OrderBy { match self { OrderBy::Alphabetical => "title", OrderBy::LastUpdated => "last_updated", - OrderBy::Score => "score", - OrderBy::Dependents => "dependencies_length", } } } @@ -38,65 +39,133 @@ impl Display for OrderBy { } } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] +#[dual_struct(derive( + Serialize, + Deserialize, + Clone, + Debug, + Eq, + PartialEq, + Hash, + Ord, + PartialOrd +))] pub struct Tag { - pub app_id: u64, + #[dual_type(ITagID)] + pub id: TagID, pub display_name: String, - #[serde(rename = "id")] - pub tag: String, } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct WorkshopItem { - pub appid: i64, - pub author: String, +fn to_external_tag(internal: Vec) -> Result, surrealdb_types::Error> { + internal + .into_iter() + .map(ExternalTag::try_from) + .collect::>() + .inspect_err(|error| error!(?error, "to_external_tag")) +} + +fn to_internal_tag(external: Vec) -> Vec { + external.into_iter().map(InternalTag::from).collect() +} + +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] +pub struct WorkshopItem { + #[dual_type(IAppID)] + pub app: AppID, + #[dual_type(IUserID)] + pub author: UserID, pub description: String, - pub id: ID, + #[dual_type(IItemID)] + pub id: ItemID, pub languages: Vec, pub last_updated: u64, #[serde(skip_serializing_if = "Option::is_none")] pub preview_url: Option, pub title: String, - pub tags: Vec, + #[dual_type(Vec, to_external = to_external_tag, to_internal = to_internal_tag)] + pub tags: Vec, pub score: f32, - pub properties: Vec>, + #[dual_type(Vec, to_external = to_external_props, to_internal = to_internal_props)] + pub properties: Vec, } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] +// Read-only, dual still needed for ID conversion +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] pub struct FullWorkshopItem { - pub appid: i64, // The steam ID of the app this belongs to - pub author: String, // Authors steam ID - pub dependants: Vec, // A list of dependants found - pub dependencies: Vec, // A list of dependencies found - pub description: String, // HTML encoded description from steam - pub id: String, // The item's ID - pub languages: Vec, // All languages found in the items description - pub last_updated: u64, // Timestamp in milliseconds - #[serde(skip_serializing_if = "Option::is_none")] + // Core identifiers + #[dual_type(IItemID)] + pub id: ItemID, // The item's ID + #[dual_type(IAppID)] + pub app: AppID, // The steam ID of the app this belongs to + + // Content information + pub title: String, // The titles name + pub description: String, // HTML encoded description from steam + #[serde(default, skip_serializing_if = "Option::is_none")] pub preview_url: Option, // The URL to the banner image - pub title: String, // The titles name - pub tags: Vec, // The list of tags found - pub score: f32, // The "quality" score assigned by steam - pub properties: Vec>, // Approved or owned properties + + // Metadata and categorisation + #[serde(default)] + #[dual_type(Vec, to_external = to_external_tag, to_internal = to_internal_tag)] + pub tags: Vec, // The list of tags found + #[dual_type(Vec, to_external = to_external_props, to_internal = to_internal_props)] + #[serde(default)] + pub properties: Vec, // Approved or owned properties + pub score: f32, // The "quality" score assigned by steam + + // Author and timing + #[dual_type(Option, to_external = to_external_user, to_internal = to_internal_user)] + pub author: Option, // Authors steam ID + pub last_updated: u64, // Timestamp in milliseconds + + // Localization + #[serde(default)] + pub languages: Vec, // All languages found in the items description + + // Dependencies + #[dual_type(Vec, to_external = to_external_full_item, to_internal = to_internal_full_item, surreal(wrap))] + #[serde(default)] + pub dependencies: Vec, // A list of dependencies found + #[dual_type(Vec, to_external = to_external_full_item, to_internal = to_internal_full_item, surreal(wrap))] + #[serde(default)] + pub dependants: Vec, // A list of dependants found } -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct Dependencies { - pub id: RecordId, - #[serde(rename = "in")] - pub this: RecordId, - #[serde(rename = "out")] - pub dependency: RecordId, + +fn to_external_user(internal: Option) -> Result, surrealdb_types::Error> { + internal.map(TryInto::try_into).transpose() } -pub fn into_string(key: &RecordIdKey) -> String { - key.to_string().replace("⟩", "").replace("⟨", "") +fn to_internal_user(external: Option) -> Option { + external.map(Into::into) } +fn to_external_full_item( + internal: Vec, +) -> Result, surrealdb_types::Error> { + internal + .into_iter() + .map(TryFrom::try_from) + .collect::>() + .inspect_err(|error| error!(?error, "to_external_full_item")) +} + +fn to_internal_full_item(external: Vec) -> Vec { + external.into_iter().map(Into::into).collect() +} + +#[derive(Serialize, Deserialize, Clone, Debug, SurrealValue)] +pub struct Dependencies { + pub id: Vec, + #[serde(rename = "in")] + pub this: IItemID, + #[serde(rename = "out")] + pub dependency: IItemID, +} /// A steam workshop app -#[expect(unused, reason = "To be used soon")] -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] pub struct App { /// The steam ID for an app - pub id: u32, + #[dual_type(IAppID)] + pub id: AppID, /// App name, I.E. Rimworld pub name: String, /// The developers primary name I.E. Ludeon Studios @@ -109,14 +178,21 @@ pub struct App { /// Whether the app is visible on the index pub available: bool, /// List of tags to select by default - pub default_tags: Vec<()>, + #[serde(default)] + #[dual_type(Vec, to_external = to_external_tag, to_internal = to_internal_tag)] + pub default_tags: Vec, + /// List of known tags + #[serde(default)] + #[dual_type(Vec, to_external = to_external_tag, to_internal = to_internal_tag)] + pub tags: Vec, } /// A workshop walker user -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct User { +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] +pub struct User { /// The steam account ID - pub id: T, + #[dual_type(IUserID)] + pub id: UserID, /// Privileged access pub admin: bool, pub banned: bool, @@ -125,18 +201,27 @@ pub struct User { #[serde(serialize_with = "serialize_chrono_as_sql_datetime")] pub last_logged_in: DateTime, } -pub fn serialize_chrono_as_sql_datetime( - x: &chrono::DateTime, - s: S, -) -> Result +pub fn serialize_chrono_as_sql_datetime(x: &DateTime, s: S) -> Result where S: Serializer, { - Into::::into(*x).serialize(s) + Into::::into(*x).serialize(s) } /// Crowdsourced metadata for an item, private version -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema, Eq, PartialEq, Hash)] +#[derive( + Serialize, + Deserialize, + Clone, + Debug, + ToSchema, + Eq, + PartialEq, + Hash, + SurrealValue, + Ord, + PartialOrd, +)] pub struct Property { pub class: Class, pub value: String, @@ -149,8 +234,18 @@ impl Display for Property { f.write_str(&self.value) } } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct PropertyExt { + +impl Into for Property { + fn into(self) -> RecordIdKey { + let mut obj = Object::new(); + obj.insert("class", self.class); + obj.insert("value", self.value); + RecordIdKey::Object(obj) + } +} + +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] +pub struct PropertyExt { /// Reasoning or justification for an inclusion pub note: Option, pub status: Status, @@ -158,73 +253,85 @@ pub struct PropertyExt { pub upvote_count: i64, /// The total upvotes pub vote_count: u64, - pub source: Source, + #[dual_type(InternalSource)] + pub source: ExternalSource, } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct WorkshopItemProperties { +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] +pub struct WorkshopItemProperties { + #[dual_type(IItemID)] #[serde(rename = "in")] - pub workshop_item: CHILD, + pub r#in: ItemID, #[serde(rename = "out")] - pub property: PROP, + pub out: Property, + #[dual_type(InternalPropertyExt)] #[serde(flatten)] - pub property_ext: PropertyExt, + pub property_ext: ExternalPropertyExt, pub vote_state: Option, } +fn to_external_props( + internal: Vec, +) -> Result, surrealdb_types::Error> { + internal + .into_iter() + .map(TryFrom::try_from) + .collect::>() +} + +fn to_internal_props( + external: Vec, +) -> Vec { + external.into_iter().map(From::from).collect() +} + /// Crowdsourced relationships for an item, used for "soft" dependencies not /// supplied by steam, private version -#[expect(unused, reason = "To be used soon")] -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct Companion { - /// Snowflake generated ID - pub id: String, - pub r#in: R, - pub out: R, - /// Reasoning or justification for an inclusion - pub note: Option, - pub status: Status, - pub upvote_count: u64, - pub vote_count: u64, - pub source: Source, -} +// #[expect(unused, reason = "To be used soon")] +// #[derive(Serialize, Deserialize, Clone, Debug, ToSchema, SurrealValue)] +// pub struct Companion { +// /// Snowflake generated ID +// pub id: String, +// pub r#in: R, +// pub out: R, +// /// Reasoning or justification for an inclusion +// pub note: Option, +// pub status: Status, +// pub upvote_count: u64, +// pub vote_count: u64, +// pub source: Source, +// } /// A voting record -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -#[expect(unused, reason = "To be used soon")] +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] pub struct Vote { /// The app this is associated with, for possible filtering - pub app_id: String, + #[dual_type(IAppID)] + pub app: AppID, pub score: f32, pub when: DateTime, } -#[derive(Clone, Debug, ToSchema, Eq, PartialEq)] -pub enum Source { +#[derive(Clone, Debug, Eq, PartialEq, SurrealValue)] +pub enum InternalSource { /// Auto-generated System, /// User submitted - User(T), + User(IUserID), } -impl serde::Serialize for Source -where - T: serde::Serialize, -{ +impl serde::Serialize for InternalSource { fn serialize(&self, serializer: S) -> Result where S: Serializer, { match self { - Source::System => serializer.serialize_str("system"), - Source::User(t) => t.serialize(serializer), + InternalSource::System => serializer.serialize_str("system"), + InternalSource::User(t) => t.serialize(serializer), } } } -impl<'de, T> serde::Deserialize<'de> for Source -where - T: serde::Deserialize<'de>, -{ +impl<'de> serde::Deserialize<'de> for InternalSource { fn deserialize(deserializer: D) -> Result where D: Deserializer<'de>, @@ -234,9 +341,9 @@ where let value = deserializer.deserialize_any(ValueVisitor)?; match value { - Value::String(str) if str == "system" => Ok(Source::System), - _ => ::deserialize(deserializer) - .map(Source::User) + Value::String(str) if str == "system" => Ok(InternalSource::System), + _ => ::deserialize(deserializer) + .map(InternalSource::User) .map_err(|_| { Error::custom("data did not match any variant of untagged enum Source") }), @@ -244,7 +351,47 @@ where } } -#[derive(Debug, ToSchema, Clone, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Hash)] +impl From for InternalSource { + fn from(value: ExternalSource) -> Self { + match value { + ExternalSource::System => Self::System, + ExternalSource::User(t) => Self::User(t.into()), + } + } +} + +#[derive(Clone, Debug, Eq, PartialEq, ToSchema, Serialize, Deserialize)] +pub enum ExternalSource { + /// Auto-generated + System, + /// User submitted + User(UserID), +} + +impl TryFrom for ExternalSource { + type Error = surrealdb_types::Error; + + fn try_from(value: InternalSource) -> Result { + match value { + InternalSource::System => Ok(ExternalSource::System), + InternalSource::User(t) => Ok(ExternalSource::User(t.try_into()?)), + } + } +} + +#[derive( + Debug, + ToSchema, + Clone, + Serialize, + Deserialize, + Eq, + PartialEq, + Ord, + PartialOrd, + Hash, + SurrealValue, +)] pub enum Class { /// Anything like addon, overhaul, bugfix, patch Type, @@ -280,6 +427,7 @@ impl Display for Class { PartialEq, Ord, PartialOrd, + SurrealValue, )] #[repr(i8)] pub enum Status { @@ -289,63 +437,25 @@ pub enum Status { Accepted = 1, } -#[derive(Serialize, Deserialize, PartialOrd, PartialEq, Eq, Debug)] -#[serde(transparent)] -struct Id(RecordId); - -impl From for Id { - fn from(value: RecordId) -> Self { - Self(value) - } -} -impl From for RecordId { - fn from(val: Id) -> Self { - val.0 - } -} - -impl Deref for Id { - type Target = RecordId; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -impl DerefMut for Id { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl salvo::oapi::ToSchema for Id { - fn to_schema( - components: &mut salvo::oapi::Components, - ) -> salvo::oapi::RefOr { - let name = salvo::oapi::naming::assign_name::(salvo::oapi::naming::NameRule::Auto); - let ref_or = salvo::oapi::RefOr::Ref(salvo::oapi::Ref::new(format!( - "#/components/schemas/{name}" - ))); - if !components.schemas.contains_key(&name) { - components.schemas.insert(name.clone(), ref_or.clone()); - let schema = salvo::oapi::Object::new().schema_type( - salvo::oapi::schema::SchemaType::basic(salvo::oapi::schema::BasicType::String), - ); - components.schemas.insert(name, schema); - } - ref_or - } +#[derive(Debug, ToSchema, Clone, Serialize, Deserialize, Eq, PartialEq, Ord, PartialOrd, Hash)] +pub struct DisplayUser { + id: UserID, + name: String, } #[cfg(test)] mod test { use serde::{Deserialize, Serialize}; - use surrealdb::RecordId; + use surrealdb_types::RecordId; - use crate::db::model::{Class, Id, Source}; + use crate::db::{ + model::{Class, Id, InternalSource, Source}, IItemID, + IUserID, + }; #[test] fn test_id_newtype() { - let id: Id = RecordId::from_table_key("items", "1").into(); + let id: Id = IItemID::from("1".to_string()).into(); let id_txt = serde_json::to_string(&id).unwrap(); let id2: Id = serde_json::from_str(&id_txt).unwrap(); assert_eq!(id, id2); @@ -355,7 +465,7 @@ mod test { #[test] fn test_source_de_ser() { - let system: Source = Source::System; + let system: InternalSource = Source::System; let system_text = serde_json::to_string(&system).unwrap(); let system2 = serde_json::from_str(&system_text).unwrap(); assert_eq!(system, system2); @@ -367,7 +477,7 @@ mod test { println!("{user_text} {system_text}"); { - let user = Source::User(RecordId::from_table_key("a", "b")); + let user = Source::User(IUserID::from("b".to_string())); let user_text = serde_json::to_string(&user).unwrap(); let user2 = serde_json::from_str(&user_text).unwrap(); assert_eq!(user, user2); @@ -376,7 +486,7 @@ mod test { #[derive(Serialize, Deserialize, Eq, PartialEq, Debug)] struct Test { - source: Source, + source: InternalSource, } let t_user = Test { source: user }; @@ -400,7 +510,7 @@ mod test { } #[tokio::test] async fn test_source_surreal() { - use surrealdb::{Surreal, engine::local::Mem}; + use surrealdb::{engine::local::Mem, Surreal}; #[derive(Serialize, Deserialize, Eq, PartialEq, Debug, Clone)] struct Foo { diff --git a/src/db/properties_actor.rs b/src/db/properties_actor.rs index 6eb7e40..23578c5 100644 --- a/src/db/properties_actor.rs +++ b/src/db/properties_actor.rs @@ -6,10 +6,11 @@ use surrealdb::{Surreal, engine::local::Db}; use crate::{ application::properties_service::PropertiesService, db::{ - model::{Source, Status}, + IUserID, + model::{InternalSource, Status}, properties_repository::PropertiesSilo, }, - domain::properties::{NewProperty, PropertiesError, VoteData}, + domain::properties::{InternalNewProperty, InternalVoteData, PropertiesError}, }; pub static PROPERTIES_ACTOR: OnceLock> = OnceLock::new(); @@ -31,13 +32,21 @@ pub struct PropertiesState { /// Messages handled by `PropertiesActor`. pub enum PropertiesMsg { NewProperty( - NewProperty, - Source, + InternalNewProperty, + InternalSource, Status, RpcReplyPort>, ), - Vote(VoteData, String, RpcReplyPort>), - Remove(VoteData, String, RpcReplyPort>), + Vote( + InternalVoteData, + IUserID, + RpcReplyPort>, + ), + Remove( + InternalVoteData, + IUserID, + RpcReplyPort>, + ), } #[async_trait] diff --git a/src/db/properties_repository.rs b/src/db/properties_repository.rs index 6d11936..a5454ec 100644 --- a/src/db/properties_repository.rs +++ b/src/db/properties_repository.rs @@ -1,14 +1,14 @@ use std::result::Result; -use surrealdb::{RecordId, Surreal, engine::local::Db}; +use surrealdb::{Surreal, engine::local::Db}; use tracing::{debug, error}; use crate::{ db::{ - ItemID, UserID, - model::{Property, Source, Status, WorkshopItemProperties}, + IItemID, IUserID, UserID, + model::{InternalSource, InternalUser, InternalWorkshopItemProperties, Property, Status}, }, - domain::properties::{NewProperty, PropertiesError, PropertiesPort, VoteData}, + domain::properties::{InternalNewProperty, InternalVoteData, PropertiesError, PropertiesPort}, }; pub struct PropertiesSilo { @@ -24,11 +24,11 @@ impl PropertiesSilo { impl PropertiesPort for PropertiesSilo { async fn create_or_link_property( &self, - new_property: NewProperty, - source: Source, + new_property: InternalNewProperty, + source: InternalSource, status: Status, ) -> Result<(), PropertiesError> { - let workshop_id = ItemID::from(new_property.workshop_item).into_recordid(); + let workshop_id = new_property.workshop_item; let test_prop = Property { class: new_property.class, @@ -69,11 +69,11 @@ impl PropertiesPort for PropertiesSilo { debug!(?similar_properties, "Similar properties exist"); return Err(PropertiesError::Conflict); } - let existing_properties: Vec> = + let existing_properties: Vec = res.take(1).unwrap_or_default(); existing_properties .iter() - .any(|prop| prop.property == test_prop) + .any(|prop| prop.out == test_prop) }; debug!(%test_prop, exists = prop_exists, "property already exists?"); @@ -96,18 +96,16 @@ impl PropertiesPort for PropertiesSilo { .bind(( "source", match source { - Source::System => Source::System, - Source::User(userid) => Source::::User(UserID::from(userid).into()), + InternalSource::System => InternalSource::System, + InternalSource::User(userid) => InternalSource::User(userid), }, )) .bind(("status", status)) .await - .map(surrealdb::Response::check) + .map(surrealdb::IndexedResults::check) { Ok(Ok(_)) => Ok(()), - Ok(Err(surrealdb::Error::Db(surrealdb::err::Error::IndexExists { .. }))) => { - Err(PropertiesError::Conflict) - } + Ok(Err(err)) if err.is_already_exists() => Err(PropertiesError::Conflict), Ok(Err(other)) => { error!(?other, "unexpected DB error"); Err(PropertiesError::Internal) @@ -119,8 +117,11 @@ impl PropertiesPort for PropertiesSilo { } } - async fn vote(&self, vote_data: VoteData, userid: String) -> Result<(), PropertiesError> { - let user = UserID::from(userid); + async fn vote( + &self, + vote_data: InternalVoteData, + user: IUserID, + ) -> Result<(), PropertiesError> { let query = self .db .query("LET $link = properties:{class: $class, value: $value}") @@ -146,14 +147,14 @@ impl PropertiesPort for PropertiesSilo { ) .bind(("class", vote_data.class)) .bind(("value", vote_data.value)) - .bind(("user", user.into_recordid())) + .bind(("user", user)) .bind(( "item", - RecordId::from_table_key("workshop_items", vote_data.item), + vote_data.item, )) .bind(("score", vote_data.score)); - match query.await.map(surrealdb::Response::check) { + match query.await.map(surrealdb::IndexedResults::check) { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => { debug!(?e, "bad vote from user"); @@ -170,10 +171,9 @@ impl PropertiesPort for PropertiesSilo { async fn remove_vote( &self, - vote_data: VoteData, - userid: String, + vote_data: InternalVoteData, + user: IUserID, ) -> Result<(), PropertiesError> { - let user = UserID::from(userid); let result = self .db .query("BEGIN TRANSACTION;") @@ -190,14 +190,11 @@ impl PropertiesPort for PropertiesSilo { .query("COMMIT TRANSACTION;") .bind(("class", vote_data.class)) .bind(("value", vote_data.value)) - .bind(("user", user.into_recordid())) - .bind(( - "item", - RecordId::from_table_key("workshop_items", vote_data.item), - )) + .bind(("user", user)) + .bind(("item", vote_data.item)) .await; - match result.map(surrealdb::Response::check) { + match result.map(surrealdb::IndexedResults::check) { Ok(Ok(_)) => Ok(()), Ok(Err(e)) => { debug!(?e, "bad vote removal from user"); diff --git a/src/db/tags_repository.rs b/src/db/tags_repository.rs new file mode 100644 index 0000000..8154d40 --- /dev/null +++ b/src/db/tags_repository.rs @@ -0,0 +1,105 @@ +use surrealdb::{Surreal, engine::local::Db}; +use tracing::error; + +use crate::{ + db::{IAppID, model::InternalTag}, + domain::tags::{TagError, TagsPort}, +}; + +pub struct TagsSilo { + db: Surreal, +} + +impl TagsSilo { + pub fn new(db: Surreal) -> Self { + Self { db } + } +} + +impl TagsPort for TagsSilo { + async fn upsert_tags(&self, app: IAppID, tags: Vec) -> Result<(), TagError> { + for tag in tags { + let query = self + .db + .query("BEGIN TRANSACTION") + .query("UPSERT tags CONTENT $tag") + .query("UPDATE $id SET tags = tags.add($record)") + .query("COMMIT") + .bind(("record", tag.id.clone())) + .bind(("tag", tag)) + .bind(("id", app.clone())); + if let Err(error) = query.await.map(surrealdb::IndexedResults::check) { + error!(?error, "failed to upsert tag"); + return Err(TagError::Internal { + msg: error.to_string(), + }); + } + } + Ok(()) + } +} + +#[cfg(test)] +mod test { + use surrealdb::{Surreal, engine::local::Mem}; + + use crate::db::{AppID, IAppID, ITagID, TagID}; + + #[tokio::test] + async fn test_upsert_tags() { + let db = Surreal::new::(()).await.unwrap(); + db.use_ns("test").use_db("test").await.unwrap(); + db.query( + "DEFINE TABLE tags TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + + -- ------------------------------ + -- FIELDS + -- ------------------------------ + + DEFINE FIELD app ON tags TYPE int PERMISSIONS FULL; + DEFINE FIELD display_name ON tags TYPE string PERMISSIONS FULL; + DEFINE FIELD id ON tags TYPE string PERMISSIONS FULL; + + -- ------------------------------ + -- INDEXES + -- ------------------------------ + + DEFINE INDEX field_app_tag ON tags FIELDS app, display_name; + DEFINE TABLE apps TYPE NORMAL SCHEMAFULL PERMISSIONS NONE; + + -- ------------------------------ + -- FIELDS + -- ------------------------------ + + + DEFINE FIELD id ON apps TYPE int PERMISSIONS FULL; + DEFINE FIELD tags ON apps TYPE set> DEFAULT [] PERMISSIONS FULL; + DEFINE FIELD tags[*] ON apps TYPE record PERMISSIONS FULL; + + -- ------------------------------ + -- INDEXES + -- ------------------------------ + + DEFINE INDEX apps_id ON apps FIELDS id;", + ) + .await + .unwrap(); + db.query("CREATE $id") + .bind(("id", IAppID::from(4i64))) + .await + .unwrap(); + db.query("UPDATE $id SET tags = tags.add($record)") + .bind(("id", IAppID::from(4i64))) + .bind(("record", ITagID::from("something".to_string()))) + .await + .unwrap(); + let stuff: Vec = db + .query("SELECT tags.map(|$v|$v.to_string()) FROM $id") + .bind(("id", IAppID::from(4i64))) + .await + .unwrap() + .take(0) + .unwrap(); + assert_eq!(stuff, vec!["tags:something"]); + } +} diff --git a/src/db/user_names_repository.rs b/src/db/user_names_repository.rs new file mode 100644 index 0000000..b12ffe2 --- /dev/null +++ b/src/db/user_names_repository.rs @@ -0,0 +1,55 @@ +use surrealdb::{Surreal, engine::local::Db}; +use tracing::error; + +use crate::{ + db::IUsernameID, + domain::user_names::{UserName, UserNameError, UserNamesPort}, +}; + +pub struct UserNamesSilo { + db: Surreal, +} + +impl UserNamesSilo { + pub fn new(db: Surreal) -> Self { + Self { db } + } +} + +impl UserNamesPort for UserNamesSilo { + async fn upsert(&self, username: UserName) -> Result<(), UserNameError> { + match self + .db + .query("UPSERT usernames CONTENT $username") + .bind(("username", username)) + .await + .map(surrealdb::IndexedResults::check) + { + Ok(Ok(..)) => Ok(()), + Err(error) | Ok(Err(error)) => { + error!(?error, "failed to upsert username"); + Err(UserNameError::Internal { + msg: error.to_string(), + }) + } + } + } + + async fn get_by_id(&self, id: IUsernameID) -> Result, UserNameError> { + match self + .db + .query("SELECT * FROM $id") + .bind(("id", id)) + .await + .map(|r| r.check().map(|mut r| r.take(0))) + { + Ok(Ok(Ok(username))) => Ok(username), + Ok(Err(error) | Ok(Err(error))) | Err(error) => { + error!(?error, "failed to get user_name by id"); + Err(UserNameError::Internal { + msg: error.to_string(), + }) + } + } + } +} diff --git a/src/domain/admin.rs b/src/domain/admin.rs new file mode 100644 index 0000000..934501d --- /dev/null +++ b/src/domain/admin.rs @@ -0,0 +1,44 @@ +use salvo::oapi::ToSchema; +use serde::{Deserialize, Serialize}; +use snafu::prelude::*; + +use crate::db::model::{InternalUser, InternalWorkshopItemProperties, Property, Status}; + +#[derive(Debug, Snafu, Clone)] +#[non_exhaustive] +pub enum AdminError { + #[snafu(display("Bad request: {msg}"))] + BadRequest { msg: String }, + #[snafu(display("Conflict"))] + Conflict, + #[snafu(display("Internal error"))] + Internal, +} + +#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] +pub struct PatchUserData { + pub id: String, + pub banned: Option, + pub admin: Option, +} + +#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] +pub struct PatchRelationshipData { + pub item: String, + #[serde(flatten)] + pub property: Property, + pub status: Status, +} + +/// Port for admin-related persistence operations. +pub trait AdminPort: Send + Sync + 'static { + async fn list_users(&self) -> Result, AdminError>; + async fn patch_user(&self, patch: PatchUserData) -> Result<(), AdminError>; + async fn list_workshop_item_properties( + &self, + ) -> Result, AdminError>; + async fn patch_workshop_item_property( + &self, + patch: PatchRelationshipData, + ) -> Result<(), AdminError>; +} diff --git a/src/domain/apps.rs b/src/domain/apps.rs new file mode 100644 index 0000000..e85e2ed --- /dev/null +++ b/src/domain/apps.rs @@ -0,0 +1,25 @@ +use snafu::prelude::*; + +use crate::db::{IAppID, model::InternalApp}; + +#[derive(Debug, Snafu, Clone)] +#[non_exhaustive] +pub enum AppError { + #[snafu(display("Bad request: {msg}"))] + BadRequest { msg: String }, + #[snafu(display("Conflict"))] + Conflict, + #[snafu(display("Internal error"))] + Internal, + #[snafu(display("Not found"))] + NotFound, +} + +/// Port for app-related persistence operations. +pub trait AppsPort: Send + Sync + 'static { + async fn list_available(&self) -> Result, AppError>; + async fn upsert(&self, app: InternalApp) -> Result<(), AppError>; + async fn remove(&self, id: IAppID) -> Result<(), AppError>; + async fn list(&self) -> Result, AppError>; + async fn get(&self, id: IAppID) -> Result; +} diff --git a/src/domain/mod.rs b/src/domain/mod.rs index 09d2bb6..4db00bd 100644 --- a/src/domain/mod.rs +++ b/src/domain/mod.rs @@ -1 +1,5 @@ +pub mod admin; +pub mod apps; pub mod properties; +pub mod tags; +pub mod user_names; diff --git a/src/domain/properties.rs b/src/domain/properties.rs index 1f27955..cd16f61 100644 --- a/src/domain/properties.rs +++ b/src/domain/properties.rs @@ -1,8 +1,12 @@ -use salvo::oapi::ToSchema; +use macros::dual_struct; use serde::{Deserialize, Serialize}; use snafu::prelude::*; +use surrealdb_types::SurrealValue; -use crate::db::model::{Class, Source, Status}; +use crate::db::{ + IItemID, IUserID, ItemID, + model::{Class, InternalSource, InternalUser, Status}, +}; #[derive(Debug, Snafu, Clone)] #[non_exhaustive] @@ -18,9 +22,10 @@ pub enum PropertiesError { } /// Data required to create/link a new property to a workshop item -#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] pub struct NewProperty { - pub workshop_item: String, + #[dual_type(IItemID)] + pub workshop_item: ItemID, pub class: Class, pub value: String, /// Reasoning or justification for an inclusion @@ -28,9 +33,10 @@ pub struct NewProperty { } /// Data required to cast or update a vote on a property -#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)] +#[dual_struct(derive(Serialize, Deserialize, Clone, Debug))] pub struct VoteData { - pub item: String, + #[dual_type(IItemID)] + pub item: ItemID, pub class: Class, pub value: String, pub score: i32, @@ -40,10 +46,14 @@ pub struct VoteData { pub trait PropertiesPort: Send + Sync + 'static { async fn create_or_link_property( &self, - new_prop: NewProperty, - source: Source, + new_prop: InternalNewProperty, + source: InternalSource, status: Status, ) -> Result<(), PropertiesError>; - async fn vote(&self, vote: VoteData, userid: String) -> Result<(), PropertiesError>; - async fn remove_vote(&self, vote: VoteData, userid: String) -> Result<(), PropertiesError>; + async fn vote(&self, vote: InternalVoteData, userid: IUserID) -> Result<(), PropertiesError>; + async fn remove_vote( + &self, + vote: InternalVoteData, + userid: IUserID, + ) -> Result<(), PropertiesError>; } diff --git a/src/domain/tags.rs b/src/domain/tags.rs new file mode 100644 index 0000000..e6cd376 --- /dev/null +++ b/src/domain/tags.rs @@ -0,0 +1,16 @@ +use snafu::prelude::*; + +use crate::db::{IAppID, model::InternalTag}; + +#[derive(Debug, Snafu, Clone)] +#[non_exhaustive] +pub enum TagError { + #[snafu(display("Internal error: {msg}"))] + Internal { msg: String }, + #[snafu(display("Not found"))] + NotFound, +} + +pub trait TagsPort: Send + Sync + 'static { + async fn upsert_tags(&self, app: IAppID, tags: Vec) -> Result<(), TagError>; +} diff --git a/src/domain/user_names.rs b/src/domain/user_names.rs new file mode 100644 index 0000000..d43da7e --- /dev/null +++ b/src/domain/user_names.rs @@ -0,0 +1,28 @@ +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; +use snafu::prelude::*; +use surrealdb_types::SurrealValue; + +use crate::db::IUsernameID; + +#[derive(Debug, Serialize, Deserialize, Clone, SurrealValue)] +pub struct UserName { + pub id: IUsernameID, + #[serde(serialize_with = "crate::db::model::serialize_chrono_as_sql_datetime")] + pub last_updated: DateTime, + pub name: String, +} + +#[derive(Debug, Snafu, Clone)] +#[non_exhaustive] +pub enum UserNameError { + #[snafu(display("Internal error: {msg}"))] + Internal { msg: String }, + #[snafu(display("Not found"))] + NotFound, +} + +pub trait UserNamesPort: Send + Sync + 'static { + async fn upsert(&self, username: UserName) -> Result<(), UserNameError>; + async fn get_by_id(&self, id: IUsernameID) -> Result, UserNameError>; +} diff --git a/src/main.rs b/src/main.rs index f1327ae..17c4135 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,15 +1,25 @@ -use std::{env, sync::Arc}; +use std::{env, path::Path, sync::Arc}; -use salvo::__private::tracing::debug; +use migrations_tool::{Migrator, Outcome}; use snafu::{Whatever, prelude::*}; -use surrealdb::{Surreal, engine::local::RocksDb, opt::auth::Root}; -use surrealdb_migrations::MigrationRunner; -use tracing::{Instrument, info_span}; +use surrealdb::{ + Connection, Surreal, + engine::{ + any::{Any, connect}, + local::{Db, RocksDb}, + }, + opt::{IntoEndpoint, auth::Root}, +}; +use tokio_stream::{StreamExt, wrappers::ReadDirStream}; +use tracing::{Instrument, debug, error, info_span}; use tracing_subscriber::fmt::format::FmtSpan; +use crate::{application::admin_service::AdminService, db::admin_repository::AdminSilo}; + mod actors; mod app_config; mod application; +mod apps; mod db; mod domain; mod processing; @@ -31,7 +41,34 @@ async fn main() -> Result<()> { .try_deserialize() .whatever_context("deserializing config")?; let span = info_span!("spawn"); - let db = Surreal::new::("./workshopdb") + + let db = setup_database(&settings) + .await + .inspect_err(|error| error!(?error, "Failed to setup db"))?; + { + let admin_service = AdminService::new(AdminSilo::new(db.clone())); + for user in &settings.admin_users { + debug!(%user, "Setting admin flag for user"); + let _ = admin_service + .patch_user(domain::admin::PatchUserData { + id: user.clone(), + banned: None, + admin: Some(true), + }) + .await + .inspect_err(|error| error!(?error, %user, "Failed to set admin flag for user")); + } + } + + actors::spawn(&settings, &db) + .instrument(info_span!(parent: &span, "spawn actors")) + .await?; + web::start(db, Arc::new(settings)).await; + Ok(()) +} + +async fn setup_database(settings: &app_config::Config) -> Result, Error> { + let db = Surreal::new::("./workshopdb".to_string()) .await .whatever_context("connecting to db")?; @@ -50,25 +87,40 @@ async fn main() -> Result<()> { // Signin as db user (root) db.signin(Root { - username: &settings.database.user, - password: &settings.database.password, + username: settings.database.user.clone(), + password: settings.database.password.clone(), }) .await .whatever_context("signing in to db")?; - debug!("checking migrations"); - // Run migrations - MigrationRunner::new(&db) - .up() - .instrument(info_span!(parent: &span, "run migrations")) + let plan = Migrator::from_files("./migrations") + .whatever_context("loading migrations")? + .with_table("_migrations") + .ignore_checksum_changes(false) + .validate() + .whatever_context("validating migrations")? + .plan(&db) .await - .whatever_context("Failed to apply migrations")?; - debug!("migrations finished"); - actors::spawn(&settings, &db) - .instrument(info_span!(parent: &span, "spawn actors")) - .await?; - web::start(db, Arc::new(settings)).await; - Ok(()) + .whatever_context("planning migrations")?; + + debug!("will apply {} migrations", plan.pending().len()); + + { + // The stream is not Unpin; pin it before polling. + let mut stream = std::pin::pin!(plan.execute(&db)); + while let Some(outcome) = stream.next().await { + match outcome.whatever_context("applying migration")? { + Outcome::Applied { id, duration } => { + debug!("applied {id} in {:?}", duration); + } + Outcome::Skipped { id, .. } => { + debug!("skipped {id}"); + } + } + } + } + + Ok(db) } /// Inserts data from either the disk cache (for development) or from stream @@ -83,7 +135,6 @@ mod test { #[derive(Serialize)] pub enum Ordering { Order(Vec), - Random, } dbg!(serde_json::to_string(&Ordering::Order(vec![true])).unwrap()); diff --git a/src/processing/join_process_actor.rs b/src/processing/join_process_actor.rs index 4211088..66a9520 100644 --- a/src/processing/join_process_actor.rs +++ b/src/processing/join_process_actor.rs @@ -1,12 +1,15 @@ -use std::mem::take; +use std::{collections::HashSet, mem::take}; use ractor::{Actor, ActorProcessingErr, ActorRef, async_trait, call}; -use snafu::{OptionExt, Whatever}; -use surrealdb::RecordId; +use snafu::{OptionExt, ResultExt, Whatever}; use tracing::error; use crate::{ - db::{item_update_actor::ItemUpdateMsg, model, model::WorkshopItem}, + db::{ + IAppID, ITagID, IUserID, + item_update_actor::ItemUpdateMsg, + model::{InternalTag, InternalWorkshopItem}, + }, processing::{ bb_actor::BBMsg, language_actor::{DetectedLanguage, LanguageMsg}, @@ -62,7 +65,7 @@ impl Actor for JoinProcessActor { let languages = call!(state.language, LanguageMsg::Detect, description.clone())?; let description = call!(state.bb, BBMsg::Process, description)?; let children = take(&mut data.children); - match Self::new_item(data, languages, description) { + match InternalWorkshopItem::try_new(data, languages, description) { Ok(item) => { state .item_update @@ -79,35 +82,46 @@ impl Actor for JoinProcessActor { } } -impl JoinProcessActor { - fn new_item( +impl InternalWorkshopItem { + fn try_new( data: IPublishedStruct, languages: Vec, description: String, - ) -> Result, Whatever> { - let app_id = data.creator_appid.whatever_context("Missing app id")?; - let item: WorkshopItem = WorkshopItem { - appid: app_id, - author: data.creator.whatever_context("Missing author")?, + ) -> Result { + let app: IAppID = data + .consumer_appid + .whatever_context("Missing app id") + .inspect_err(|_| error!(?data, "creating new item"))? + .into(); + + let author = IUserID::from( + data.creator + .whatever_context("Missing author")? + .parse::() + .whatever_context("Invalid author format")?, + ); + Ok(Self { + app: app.clone(), + author, languages, description, - id: RecordId::from_table_key("workshop_items", data.publishedfileid), + id: data.publishedfileid.into(), title: data.title.whatever_context("Missing title")?, - preview_url: data.preview_url, + preview_url: data + .preview_url + .or_else(|| data.previews.first().map(|preview| preview.url.clone())), last_updated: data.time_updated.unwrap_or_default() as _, tags: data .tags .iter() - .cloned() - .map(|tag| model::Tag { - app_id: app_id as _, - display_name: tag.display_name, - tag: tag.tag, + .map(|tag| InternalTag { + // app: app.clone(), + id: ITagID::from(tag.tag.clone()), + display_name: tag.display_name.clone(), }) .collect::>(), score: data.vote_data.map(|votes| votes.score).unwrap_or_default(), properties: vec![], - }; - Ok(item) + }) } } diff --git a/src/processing/language_actor.rs b/src/processing/language_actor.rs index 30ac8b9..5d0e7ce 100644 --- a/src/processing/language_actor.rs +++ b/src/processing/language_actor.rs @@ -1,15 +1,18 @@ -use std::{collections::HashMap, convert::Into, fmt}; +use std::{ + collections::{HashMap, HashSet}, + convert::Into, + fmt, +}; use lingua::{ Language, - Language::{Chinese, English, Japanese, Korean, Portuguese, Russian, Spanish}, + Language::{Chinese, English, French, Japanese, Korean, Portuguese, Russian, Spanish}, LanguageDetector, LanguageDetectorBuilder, }; use ractor::{Actor, ActorProcessingErr, ActorRef, RpcReplyPort, async_trait}; use salvo::prelude::ToSchema; use serde_repr::{Deserialize_repr, Serialize_repr}; - -use crate::processing::language_actor::DetectedLanguage::Unknown; +use surrealdb_types::{Error, Kind, SurrealValue, Value}; // The threshold of total words a language must be, to be considered valid for // detection. @@ -27,6 +30,7 @@ const WORD_PERCENTAGE: f32 = 0.2; PartialEq, Ord, PartialOrd, + Hash, )] #[repr(u8)] pub enum DetectedLanguage { @@ -38,6 +42,7 @@ pub enum DetectedLanguage { Korean = 5, Spanish = 6, Portuguese = 7, + French = 9, Unknown = 0, } @@ -56,7 +61,35 @@ impl From for DetectedLanguage { English => Self::English, Spanish => Self::Spanish, Portuguese => Self::Portuguese, - _ => Unknown, + French => Self::French, + _ => Self::Unknown, + } + } +} + +impl SurrealValue for DetectedLanguage { + fn kind_of() -> Kind { + Kind::Int + } + + fn into_value(self) -> Value { + Value::Number((self as i64).into()) + } + + fn from_value(value: Value) -> Result + where + Self: Sized, + { + match value.into_u8()? { + 1 => Ok(DetectedLanguage::English), + 2 => Ok(DetectedLanguage::Russian), + 3 => Ok(DetectedLanguage::Chinese), + 4 => Ok(DetectedLanguage::Japanese), + 5 => Ok(DetectedLanguage::Korean), + 6 => Ok(DetectedLanguage::Spanish), + 7 => Ok(DetectedLanguage::Portuguese), + 9 => Ok(DetectedLanguage::French), + _ => Ok(DetectedLanguage::Unknown), } } } diff --git a/src/processing/ml_queue_actor.rs b/src/processing/ml_queue_actor.rs index 89a9205..886d6e9 100644 --- a/src/processing/ml_queue_actor.rs +++ b/src/processing/ml_queue_actor.rs @@ -1,15 +1,16 @@ use classification::actor::ExtractionMsg; use ractor::{Actor, ActorProcessingErr, ActorRef, async_trait, call}; use snafu::{ResultExt, Whatever}; -use surrealdb::{RecordId, Surreal, engine::local::Db}; +use surrealdb::{Surreal, engine::local::Db}; use tracing::{debug, error, info}; use crate::{ db::{ - model::{Class, Source, Status}, + IItemID, + model::{Class, InternalSource, Status}, properties_actor::PropertiesMsg, }, - domain::properties::NewProperty, + domain::properties::InternalNewProperty, }; pub struct MLQueueActor; @@ -28,7 +29,7 @@ pub struct MLQueueState { pub enum MLQueueMsg { /// Enqueue a workshop item id (record id) to be sent to the ML extractor - Process(RecordId), + Process(IItemID), } #[async_trait] @@ -57,8 +58,8 @@ impl Actor for MLQueueActor { ) -> Result<(), ActorProcessingErr> { match message { MLQueueMsg::Process(id) => { - if let Err(e) = process_one(state, &id).await { - error!(?e, record=%id, "processing ML extraction"); + if let Err(e) = process_one(state, id.clone()).await { + error!(?e, record=?id, "processing ML extraction"); } } } @@ -66,12 +67,12 @@ impl Actor for MLQueueActor { } } -async fn process_one(state: &mut MLQueueState, id: &RecordId) -> Result<(), Whatever> { +async fn process_one(state: &mut MLQueueState, workshop_item: IItemID) -> Result<(), Whatever> { // Load minimal fields needed let mut resp = state .database .query("SELECT title, description FROM $id") - .bind(("id", id.clone())) + .bind(("id", workshop_item.clone())) .await .whatever_context("Querying item for ML extraction")?; let title: Option = resp @@ -81,7 +82,10 @@ async fn process_one(state: &mut MLQueueState, id: &RecordId) -> Result<(), What .take((0, "description")) .whatever_context("Taking description from response")?; let (Some(title), Some(description)) = (title, description) else { - debug!(record=%id, "No item found or missing fields for ML extraction"); + debug!( + ?workshop_item, + "No item found or missing fields for ML extraction" + ); return Ok(()); }; @@ -92,7 +96,7 @@ async fn process_one(state: &mut MLQueueState, id: &RecordId) -> Result<(), What rpc_reply_port: reply }) { Ok(Ok(props)) => { - info!(record=%id, props=?props, "ML extraction completed"); + info!(?workshop_item, ?props, "ML extraction completed"); for (class, value) in props .genres @@ -103,13 +107,13 @@ async fn process_one(state: &mut MLQueueState, id: &RecordId) -> Result<(), What .chain(props.features.into_iter().map(|v| (Class::Feature, v))) { match call!(state.property_actor, |reply| PropertiesMsg::NewProperty( - NewProperty { - workshop_item: id.key().to_string().replace("⟩", "").replace("⟨", ""), + InternalNewProperty { + workshop_item: workshop_item.clone(), class: class.clone(), value: value.clone(), note: None, }, - Source::System, + InternalSource::System, Status::Accepted, reply )) { @@ -124,10 +128,10 @@ async fn process_one(state: &mut MLQueueState, id: &RecordId) -> Result<(), What } } Ok(Err(err)) => { - error!(record=%id, ?err, "ML extraction failed"); + error!(record=?workshop_item, ?err, "ML extraction failed"); } Err(err) => { - error!(record=%id, ?err, "ML extractor RPC failed"); + error!(record=?workshop_item, ?err, "ML extractor RPC failed"); } } Ok(()) diff --git a/src/steam/mod.rs b/src/steam/mod.rs index 215c2e2..b1341a4 100644 --- a/src/steam/mod.rs +++ b/src/steam/mod.rs @@ -1,3 +1,5 @@ #[allow(clippy::all)] pub mod model; pub mod steam_download_actor; +pub mod steam_tag_actor; +pub mod steam_user_actor; diff --git a/src/steam/model.rs b/src/steam/model.rs index 53f1a8a..8446a4f 100644 --- a/src/steam/model.rs +++ b/src/steam/model.rs @@ -78,7 +78,7 @@ pub enum EPublishedFileInfoMatchingFileType { pub struct GetPage { pub query_type: EPublishedFileQueryType, pub numperpage: u32, - pub appid: u32, + pub appid: i64, pub return_tags: bool, pub return_children: bool, pub return_details: bool, @@ -147,7 +147,7 @@ impl TryFrom<&SteamRoot> for GetPage { #[expect(clippy::missing_docs_in_private_items)] #[derive(Serialize, Deserialize, Clone, Debug)] pub struct Child { - pub publishedfileid: String, + pub publishedfileid: i64, pub sortorder: i64, pub file_type: i64, } @@ -204,9 +204,11 @@ pub struct IPublishedStruct { pub num_children: Option, pub num_comments_public: Option, pub num_reports: Option, + #[serde(default)] + pub previews: Vec, pub preview_file_size: Option, pub preview_url: Option, - pub publishedfileid: String, + pub publishedfileid: i64, pub result: i64, pub revision: Option, pub revision_change_number: Option, @@ -227,6 +229,16 @@ pub struct IPublishedStruct { #[serde(default)] pub workshop_file: bool, } + +#[derive(Serialize, Deserialize, Clone, Debug)] +pub struct Preview { + pub previewid: String, + pub sortorder: i64, + pub url: String, + pub size: i64, + pub filename: String, + pub preview_type: i64, +} #[derive(Serialize, Deserialize, Clone, Debug)] pub struct IPublishedResponse { pub total: i64, @@ -245,6 +257,31 @@ pub struct VoteData { pub votes_down: usize, } +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct SteamUser { + pub steamid: i64, + pub communityvisibilitystate: i64, + pub profilestate: Option, + pub personaname: String, + pub profileurl: String, + pub avatar: String, + pub avatarmedium: String, + pub avatarfull: String, + pub avatarhash: String, + pub lastlogoff: Option, + pub personastate: i64, + pub realname: Option, + pub primaryclanid: Option, + pub timecreated: Option, + pub personastateflags: Option, + pub loccountrycode: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct SteamUserResponse { + pub players: Vec, +} + #[cfg(test)] mod test { use std::fs::read_to_string; diff --git a/src/steam/steam_download_actor.rs b/src/steam/steam_download_actor.rs index e998e5d..d9ea8e4 100644 --- a/src/steam/steam_download_actor.rs +++ b/src/steam/steam_download_actor.rs @@ -1,6 +1,7 @@ use std::{ + collections::HashMap, ops::Add, - sync::Arc, + sync::{Arc, OnceLock}, time::{Duration, SystemTime, UNIX_EPOCH}, }; @@ -8,20 +9,22 @@ use ractor::{Actor, ActorProcessingErr, ActorRef, async_trait}; use reqwest::Client; use snafu::{ResultExt, Whatever}; use surrealdb::{Surreal, engine::local::Db}; -use tracing::{debug, error, info}; +use tokio::task::JoinHandle; +use tracing::{Instrument, debug, error, info, info_span}; use crate::{ - db::item_update_actor::ItemUpdateMsg, + db::{IAppID, item_update_actor::ItemUpdateMsg}, steam::model::{EPublishedFileQueryType, GetPage, IPublishedResponse, SteamRoot}, }; +pub static DOWNLOAD_ACTOR: OnceLock> = OnceLock::new(); + pub struct SteamDownloadActor {} pub struct SteamDownloadArgs { pub steam_token: Arc, pub item_processing_actor_ref: ActorRef, pub database: Surreal, - pub app_id: u32, pub client: Client, pub force: bool, } @@ -29,10 +32,14 @@ pub struct SteamDownloadState { client: Client, steam_token: Arc, item_processing_actor_ref: ActorRef, + apps: HashMap>, + database: Surreal, } pub enum SteamDownloadMsg { - Download { app_id: u32, first_page: GetPage }, + Download { app: IAppID, first_page: GetPage }, + AddApp(IAppID), + RemoveApp(IAppID), } #[async_trait] impl Actor for SteamDownloadActor { @@ -45,56 +52,60 @@ impl Actor for SteamDownloadActor { myself: ActorRef, args: Self::Arguments, ) -> Result { - // ToDo: do this per app - let timestamp: Option = args + let apps: Vec = args .database - .query("SELECT last_updated FROM workshop_items ORDER BY last_updated DESC LIMIT 1") - .await - .unwrap() - .take((0, "last_updated")) - .unwrap(); - let timestamp = timestamp.unwrap_or(0); - let time_since = SystemTime::now() - .duration_since(UNIX_EPOCH.add(Duration::from_secs(timestamp))) - .unwrap(); - let h12 = Duration::from_secs(60 * 60 * 12); - let message_builder = move || SteamDownloadMsg::Download { - app_id: args.app_id, - first_page: GetPage { - query_type: EPublishedFileQueryType::RankedByLastUpdatedDate, - ..Default::default() - }, - }; - if time_since > h12 || args.force { - myself.send_message(message_builder())?; - info!(period = %humantime::Duration::from(time_since), "newest mod is at least 12 hours out of date; running update now"); - } + .query("SELECT id.id() AS id FROM apps WHERE enabled = true") + // .instrument(info_span!("select enabled apps")) + .await? + .take((0, "id"))?; - myself.send_interval(h12, message_builder); - Ok(Self::State { + let mut state = Self::State { client: args.client, steam_token: args.steam_token, item_processing_actor_ref: args.item_processing_actor_ref, - }) + apps: HashMap::new(), + database: args.database, + }; + for app in apps { + let app = app.try_into_external()?.into(); + start_downloader(&myself, &mut state, app, args.force) + .instrument(info_span!("start downloader", ?app)) + .await; + } + + DOWNLOAD_ACTOR.get_or_init(|| myself); + Ok(state) } async fn handle( &self, - _: ActorRef, + myself: ActorRef, message: Self::Msg, state: &mut Self::State, ) -> Result<(), ActorProcessingErr> { match message { - SteamDownloadMsg::Download { app_id, first_page } => { - if let Err(e) = download( + SteamDownloadMsg::Download { app, first_page } => { + if let Err(error) = download( state, - app_id, + app.clone(), first_page, state.item_processing_actor_ref.clone(), ) .await { - error!("Downloading workshop items for {app_id} with err: {e:?}"); + error!(?app, ?error, "Downloading workshop items"); + } + } + SteamDownloadMsg::AddApp(app) => { + if !state.apps.contains_key(&app) { + let app = app.try_into_external()?.into(); + start_downloader(&myself, state, app, false).await; + } + } + SteamDownloadMsg::RemoveApp(app) => { + if let Some(handle) = state.apps.remove(&app) { + handle.abort(); + info!(?app, "Stopped downloading workshop items"); } } } @@ -105,15 +116,19 @@ impl Actor for SteamDownloadActor { async fn download( state: &mut SteamDownloadState, - app_id: u32, + app: IAppID, mut page: GetPage, database_writer_actor_ref: ActorRef, ) -> Result<(), Whatever> { - page.appid = app_id; + let app = app + .try_into_external() + .whatever_context("converting app id")? + .into(); + page.appid = app; let mut total = i64::MAX; let mut downloaded = 0; - while total >= downloaded { - page.appid = app_id; + while total > downloaded { + page.appid = app; let request = page .into_request(&state.client, &state.steam_token) .whatever_context("building download request")?; @@ -142,9 +157,52 @@ async fn download( progress = (downloaded * 100 / total * 100) / 100, downloaded, expected = total, - app_id, + ?app, "Downloaded items" ); } Ok(()) } + +async fn start_downloader( + myself: &ActorRef, + state: &mut SteamDownloadState, + app: i64, // Function needs to be infalliable, so, we handle the converion outside here + force: bool, +) { + let timestamp: Option = state + .database + .query( + "SELECT last_updated FROM workshop_items WHERE appid = $appid ORDER BY last_updated \ + DESC LIMIT 1", + ) + .bind(("appid", app)) + .await + .unwrap() + .take((0, "last_updated")) + .unwrap(); + let timestamp = timestamp.unwrap_or(0); + let time_since = SystemTime::now() + .duration_since(UNIX_EPOCH.add(Duration::from_secs(timestamp))) + .unwrap(); + let h12 = Duration::from_hours(12); + let message_builder = move || SteamDownloadMsg::Download { + app: IAppID::from(app), + first_page: GetPage { + query_type: EPublishedFileQueryType::RankedByLastUpdatedDate, + ..Default::default() + }, + }; + if time_since > h12 || force { + let _ = myself.send_message(message_builder()); + info!(period = %humantime::Duration::from(time_since), app = ?app, "newest mod is at least 12 hours out of date; running update now"); + } + + if let Some(old) = state.apps.insert( + IAppID::from(app), + myself.send_interval(h12, message_builder), + ) { + // Remember to abort the old timer + old.abort(); + } +} diff --git a/src/steam/steam_tag_actor.rs b/src/steam/steam_tag_actor.rs new file mode 100644 index 0000000..322fec9 --- /dev/null +++ b/src/steam/steam_tag_actor.rs @@ -0,0 +1,177 @@ +use std::time::Duration; + +use ractor::{Actor, ActorProcessingErr, ActorRef, async_trait}; +use reqwest::Client; +use scraper::{Html, Selector}; +use surrealdb::{Surreal, engine::local::Db}; +use tracing::{debug, error, info}; + +use crate::{ + application::{apps_service::AppsService, tags_service::TagsService}, + db::{ + IAppID, ITagID, apps_repository::AppsSilo, model::InternalTag, tags_repository::TagsSilo, + }, +}; + +pub struct SteamTagActor; + +pub struct SteamTagArgs { + pub database: Surreal, + pub client: Client, +} + +pub struct SteamTagState { + client: Client, + apps: AppsService, + tags: TagsService, +} + +pub enum SteamTagMsg { + Update, +} + +#[async_trait] +impl Actor for SteamTagActor { + type Arguments = SteamTagArgs; + type Msg = SteamTagMsg; + type State = SteamTagState; + + async fn pre_start( + &self, + myself: ActorRef, + args: Self::Arguments, + ) -> Result { + // Trigger initial update + myself.cast(SteamTagMsg::Update)?; + myself.send_interval(Duration::from_hours(24), || SteamTagMsg::Update); + + Ok(SteamTagState { + client: args.client, + apps: AppsService::new(AppsSilo::new(args.database.clone())), + tags: TagsService::new(TagsSilo::new(args.database)), + }) + } + + async fn handle( + &self, + _: ActorRef, + message: Self::Msg, + state: &mut Self::State, + ) -> Result<(), ActorProcessingErr> { + match message { + SteamTagMsg::Update => { + let apps = match state.apps.list_available().await { + Ok(apps) => apps, + Err(error) => { + error!(?error, "Failed to list available apps"); + return Ok(()); + } + }; + + for app in apps { + info!(app = ?app.id, app_name = %app.name, "Scraping tags for app"); + let url = format!( + "https://steamcommunity.com/app/{}/workshop/", + i64::from(app.clone().id.clone().try_into_external()?) + ); + match state.client.get(&url).send().await { + Ok(resp) => { + if let Ok(html) = resp.text().await { + let tags = extract_tags(&app.id, &html); + debug!(app = ?app.id, tag_count = tags.len(), "Extracted tags"); + if let Err(error) = + state.tags.update_tags(app.id.clone(), tags).await + { + error!(?error, app = ?app.id, "Failed to update tags"); + } + } + } + Err(error) => { + error!(?error, app = ?app.id, "Failed to fetch workshop page"); + } + } + } + } + } + Ok(()) + } +} + +fn extract_tags(app: &IAppID, html: &str) -> Vec { + Html::parse_document(html) + .select(&Selector::parse(".tag_label").unwrap()) + .filter_map(|node| { + node.text() + .collect::() + .split("\u{a0}") + .next() + .map(String::from) + }) + .map(|text| InternalTag { + id: ITagID::from(text.clone()), + display_name: text.clone(), + }) + .collect::>() +} +#[cfg(test)] +mod tests { + use scraper::{Html, Selector}; + + #[test] + fn test_extract_tags() { + let html = r#" +
+
Browse By Tag
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ "#; + let document = Html::parse_document(html); + let tags = document + .select(&Selector::parse(".tag_label").unwrap()) + .map(|node| { + node.text() + .collect::() + .split("\u{a0}") + .next() + .unwrap() + .to_string() + }) + .collect::>(); + assert_eq!( + tags, + vec![ + "Mod", + "Translation", + "Scenario", + "0.14", + "0.15", + "0.16", + "0.17", + "0.18", + "0.19", + "1.0", + "1.1", + "1.2", + "1.3", + "1.4", + "1.5", + "1.6" + ] + ); + } +} diff --git a/src/steam/steam_user_actor.rs b/src/steam/steam_user_actor.rs new file mode 100644 index 0000000..2456a95 --- /dev/null +++ b/src/steam/steam_user_actor.rs @@ -0,0 +1,168 @@ +use std::{collections::HashSet, sync::Arc, time::Duration}; + +use itertools::Itertools; +use ractor::{Actor, ActorProcessingErr, ActorRef, async_trait}; +use reqwest::{Client, Response, StatusCode}; +use surrealdb::{Surreal, engine::local::Db}; +use tokio::{sync::mpsc, task::JoinHandle, time::sleep}; +use tracing::{debug, error}; + +use crate::{ + application::user_names_service::UserNamesService, + db::{IUsernameID, user_names_repository::UserNamesSilo}, + steam::model::{SteamRoot, SteamUserResponse}, +}; + +pub struct SteamUserActor; + +pub struct SteamUserArgs { + pub steam_token: Arc, + pub database: Surreal, + pub client: Client, +} + +pub struct SteamUserState { + pub sender: mpsc::Sender, + pub handle: JoinHandle<()>, +} + +impl Drop for SteamUserState { + fn drop(&mut self) { + self.handle.abort(); + } +} + +pub enum SteamUserMsg { + Fetch(IUsernameID), +} + +#[async_trait] +impl Actor for SteamUserActor { + type Arguments = SteamUserArgs; + type Msg = SteamUserMsg; + type State = SteamUserState; + + async fn pre_start( + &self, + _: ActorRef, + args: Self::Arguments, + ) -> Result { + let (tx, mut rx) = mpsc::channel(100); + + let user_names_service = UserNamesService::new(UserNamesSilo::new(args.database)); + + // Ractor doesn't really give us a good way to model this kind of work, hence + // why this is a task instead. It's desirable to batch this work here + // because we're trying to minimise calls to Steams API. + let handle = tokio::spawn(async move { + let mut total_processed = 0; + let mut user_ids: HashSet = HashSet::with_capacity(200); + loop { + // Process the first message to ensure that we sleep the task until there is + // work + let Some(first): Option = rx.recv().await else { + break; + }; + + if should_update_user(&user_names_service, first.clone()).await { + user_ids.insert(first); + } + + while let Ok(next) = rx.try_recv() { + if should_update_user(&user_names_service, next.clone()).await { + user_ids.insert(next); + } + if user_ids.len() == 100 { + break; + } + } + + if user_ids.is_empty() { + continue; + } + + let id_string = user_ids + .drain() + .map(|id| i64::from(id.try_into_external().unwrap()).to_string()) + .join(","); + let url = format!( + "https://api.steampowered.com/ISteamUser/GetPlayerSummaries/v2/?key={}&steamids={id_string}", + args.steam_token + ); + + debug!(%total_processed, next_batch = user_ids.len(), "Fetching player summaries from Steam"); + // Retry up to 3 times + for _ in 0..3 { + match args + .client + .get(&url) + .send() + .await + .and_then(Response::error_for_status) + { + Ok(resp) => match resp.json::>().await { + Ok(root) => { + for users in root.response.players { + if let Err(error) = user_names_service + .update_user_name( + IUsernameID::from(users.steamid), + users.personaname, + ) + .await + { + error!(?error, "Failed to update user name"); + break; + } + } + } + Err(error) => { + error!(?error, "Failed to deserialize SteamUserResponse"); + break; + } + }, + Err(error) => { + // Back off and retry + if error.status() == Some(StatusCode::TOO_MANY_REQUESTS) { + sleep(Duration::from_secs(10)).await; + continue; + } + error!(%error, "Failed to fetch player summaries from Steam"); + } + } + } + total_processed += user_ids.len(); + user_ids.clear(); + } + }); + + Ok(SteamUserState { sender: tx, handle }) + } + + async fn handle( + &self, + _: ActorRef, + message: Self::Msg, + state: &mut Self::State, + ) -> Result<(), ActorProcessingErr> { + match message { + SteamUserMsg::Fetch(id) => { + if let Err(error) = state.sender.send(id).await { + error!(?error, "Failed to send steam ID to worker task"); + panic!("Failed to send steam ID to worker task"); + } + } + } + Ok(()) + } +} + +async fn should_update_user( + user_names_service: &UserNamesService, + id: IUsernameID, +) -> bool { + user_names_service + .should_update_user(id) + .await + .inspect_err(|error| error!(?error, "Failed to check if user should be updated")) + .unwrap_or(true) +} diff --git a/src/web/admin.rs b/src/web/admin.rs index 4a137a1..86feed4 100644 --- a/src/web/admin.rs +++ b/src/web/admin.rs @@ -1,134 +1,131 @@ -use reqwest::StatusCode; +use ractor::{ActorProcessingErr, RactorErr, call}; use salvo::{ - Depot, Response, Writer, handler, - oapi::{ToSchema, extract::JsonBody}, - prelude::{Json, endpoint}, + Writer, + oapi::extract::JsonBody, + prelude::{Json, StatusCode, StatusError, endpoint}, }; -use serde::{Deserialize, Serialize}; -use surrealdb::{Surreal, engine::local::Db}; -use tracing::error; +use snafu::{ErrorCompat, prelude::*}; -use crate::db::{ - ItemID, UserID, - model::{Property, Status, User, WorkshopItemProperties}, +use crate::{ + db::{ + admin_actor::{ADMIN_ACTOR, AdminMsg}, + model::{ExternalUser, ExternalWorkshopItemProperties, InternalUser}, + }, + domain::admin::{AdminError, PatchRelationshipData, PatchUserData}, }; -#[endpoint] -pub async fn get_users(depot: &mut Depot, response: &mut Response) { - match depot - .obtain::>() - .expect("getting shared state") - .query("SELECT record::id(id) as id, * FROM users") - .await - .map(|mut q| q.take(0)) - { - Ok(Ok(results)) => { - response.render(Json::>>(results)); - } - Ok(Err(e)) | Err(e) => { - error!("{e:?}"); - response.status_code(StatusCode::INTERNAL_SERVER_ERROR); +pub type Result = std::result::Result; +pub type Error = StatusError; + +#[derive(Debug, Snafu)] +#[non_exhaustive] +#[snafu(visibility(pub(crate)))] +enum InnerError { + #[snafu(display("Bad request: {msg}"))] + BadRequest { + msg: String, + }, + Conflict, + InternalError, +} + +impl InnerError { + pub fn status_code(&self) -> StatusCode { + match self { + InnerError::BadRequest { .. } => StatusCode::BAD_REQUEST, + InnerError::Conflict => StatusCode::CONFLICT, + InnerError::InternalError => StatusCode::INTERNAL_SERVER_ERROR, } } } -#[endpoint] -pub async fn patch_user(data: JsonBody, depot: &mut Depot, response: &mut Response) { - let id = UserID::from(data.0.id); - if let Some(banned) = data.0.banned { - let res = depot - .obtain::>() - .expect("getting shared state") - .query("UPDATE $user SET banned=$banned") - .bind(("user", id.clone())) - .bind(("banned", banned)) - .await; - if let Err(e) = res { - error!("{e:?}"); - response.status_code(StatusCode::INTERNAL_SERVER_ERROR); - return; - } +impl From for StatusError { + fn from(value: InnerError) -> Self { + let mut error = StatusError::internal_server_error(); + error.code = value.status_code(); + error.name = value + .status_code() + .canonical_reason() + .unwrap_or_default() + .to_string(); + error.brief = value.to_string(); + error.detail = value.backtrace().map(ToString::to_string); + error } +} - if let Some(admin) = data.0.admin { - let res = depot - .obtain::>() - .expect("getting shared state") - .query("UPDATE $user SET $admin=admin") - .bind(("user", id)) - .bind(("admin", admin)) - .await; - if let Err(e) = res { - error!("{e:?}"); - response.status_code(StatusCode::INTERNAL_SERVER_ERROR); - return; +impl From for InnerError { + fn from(_: ActorProcessingErr) -> Self { + Self::InternalError + } +} +impl From> for InnerError { + fn from(_: RactorErr) -> Self { + Self::InternalError + } +} +impl From for InnerError { + fn from(value: AdminError) -> Self { + match value { + AdminError::BadRequest { msg } => Self::BadRequest { msg }, + AdminError::Conflict => Self::Conflict, + AdminError::Internal => Self::InternalError, } } - response.status_code(StatusCode::NO_CONTENT); } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct PatchUser { - pub id: String, - pub banned: Option, - pub admin: Option, +#[endpoint] +pub async fn get_users() -> Result>, StatusError> { + let actor = ADMIN_ACTOR + .get() + .cloned() + .ok_or(InnerError::InternalError)?; + let users: Vec = call!(actor, AdminMsg::ListUsers) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + let users: Vec = users + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .map_err(|_| InnerError::InternalError)?; + Ok(Json(users)) } #[endpoint] -pub async fn get_workshop_item_properties(depot: &mut Depot, response: &mut Response) { - match depot - .obtain::>() - .expect("getting shared state") - .query( - "SELECT record::id(in) as in, out.*.id.{class,value} as out, source.to_string(), \ - id.to_string(), * FROM workshop_item_properties", - ) - .await - .map(|mut q| q.take(0)) - { - Ok(Ok(results)) => { - response.render(Json::>>( - results, - )); - } - Ok(Err(e)) | Err(e) => { - error!("{e:?}"); - response.status_code(StatusCode::INTERNAL_SERVER_ERROR); - } - } +pub async fn patch_user(data: JsonBody) -> Result<()> { + let actor = ADMIN_ACTOR + .get() + .cloned() + .ok_or(InnerError::InternalError)?; + call!(actor, |reply| AdminMsg::PatchUser(data.0, reply)) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + Ok(()) } -#[handler] -pub async fn patch_workshop_item_properties( - data: JsonBody, - depot: &mut Depot, - response: &mut Response, -) { - let res = depot - .obtain::>() - .expect("getting shared state") - .query("LET $link = properties:{class: $class, value: $value}") - .query( - "UPDATE ONLY workshop_item_properties SET status=$status WHERE in = $item AND out = \ - $link;", - ) - .bind(("class", data.0.property.class)) - .bind(("value", data.0.property.value)) - .bind(("item", ItemID::from(data.0.item).into_recordid())) - .bind(("status", data.0.status)) - .await; - if let Err(e) = res { - error!("{e:?}"); - response.status_code(StatusCode::INTERNAL_SERVER_ERROR); - return; - } - response.status_code(StatusCode::NO_CONTENT); +#[endpoint] +pub async fn get_workshop_item_properties() -> Result>> { + todo!() + // let actor = ADMIN_ACTOR + // .get() + // .cloned() + // .ok_or(InnerError::InternalError)?; + // let list = call!(actor, AdminMsg::ListWorkshopItemProperties) + // .map_err(InnerError::from)? + // .map_err(InnerError::from)?; + // Ok(Json(list)) } -#[derive(Serialize, Deserialize, Clone, Debug, ToSchema)] -pub struct PatchRelationship { - pub item: String, - #[serde(flatten)] - pub property: Property, - pub status: Status, +#[endpoint] +pub async fn patch_workshop_item_properties(data: JsonBody) -> Result<()> { + let actor = ADMIN_ACTOR + .get() + .cloned() + .ok_or(InnerError::InternalError)?; + call!(actor, |reply| AdminMsg::PatchWorkshopItemProperty( + data.0, reply + )) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + Ok(()) } diff --git a/src/web/apps.rs b/src/web/apps.rs new file mode 100644 index 0000000..363ea28 --- /dev/null +++ b/src/web/apps.rs @@ -0,0 +1,143 @@ +use ractor::{ActorProcessingErr, RactorErr, call}; +use reqwest::StatusCode; +use salvo::{ + http::StatusError, + oapi::{ + endpoint, + extract::{JsonBody, PathParam, QueryParam}, + }, + prelude::*, +}; +use snafu::{ErrorCompat, Snafu}; + +use crate::{ + db::{ + AppID, + apps_actor::{APPS_ACTOR, AppsMsg}, + model::ExternalApp, + }, + domain::apps::AppError, +}; + +pub type Result = std::result::Result; +pub type Error = StatusError; + +#[derive(Debug, Snafu)] +#[non_exhaustive] +#[snafu(visibility(pub(crate)))] +enum InnerError { + #[snafu(display("Bad request: {msg}"))] + BadRequest { + msg: String, + }, + Conflict, + InternalError, + Unavailable, + NotFound, +} + +impl InnerError { + pub fn status_code(&self) -> StatusCode { + match self { + InnerError::BadRequest { .. } => StatusCode::BAD_REQUEST, + InnerError::Conflict => StatusCode::CONFLICT, + InnerError::InternalError => StatusCode::INTERNAL_SERVER_ERROR, + InnerError::Unavailable => StatusCode::SERVICE_UNAVAILABLE, + InnerError::NotFound => StatusCode::NOT_FOUND, + } + } +} + +impl From for StatusError { + fn from(value: InnerError) -> Self { + let mut error = StatusError::internal_server_error(); + error.code = value.status_code(); + error.name = value + .status_code() + .canonical_reason() + .unwrap_or_default() + .to_string(); + error.brief = value.to_string(); + error.detail = value.backtrace().map(ToString::to_string); + error + } +} + +impl From for InnerError { + fn from(_: ActorProcessingErr) -> Self { + Self::InternalError + } +} +impl From> for InnerError { + fn from(_: RactorErr) -> Self { + Self::InternalError + } +} +impl From for InnerError { + fn from(value: AppError) -> Self { + match value { + AppError::BadRequest { msg } => Self::BadRequest { msg }, + AppError::Conflict => Self::Conflict, + AppError::Internal => Self::InternalError, + AppError::NotFound => Self::NotFound, + } + } +} + +#[endpoint] +pub async fn list_available() -> Result>> { + let actor = APPS_ACTOR.get().ok_or(InnerError::Unavailable)?; + let apps = call!(actor, AppsMsg::ListAvailable) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + let apps: Vec = apps + .into_iter() + .map(TryFrom::try_from) + .collect::>() + .map_err(|_| InnerError::InternalError)?; + Ok(Json(apps)) +} + +#[endpoint] +pub async fn upsert(app: JsonBody) -> Result<()> { + let actor = APPS_ACTOR.get().ok_or(InnerError::Unavailable)?; + call!(actor, |reply| AppsMsg::Upsert(app.0.into(), reply)) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + Ok(()) +} +#[endpoint] +pub async fn remove(id: QueryParam) -> Result<()> { + let actor = APPS_ACTOR.get().ok_or(InnerError::Unavailable)?; + call!(actor, |reply| AppsMsg::Remove( + id.into_inner().into(), + reply + )) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + Ok(()) +} + +#[endpoint] +pub async fn list() -> Result>> { + let actor = APPS_ACTOR.get().ok_or(InnerError::Unavailable)?; + let apps = call!(actor, AppsMsg::List) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + let apps: Vec = apps + .into_iter() + .map(TryFrom::try_from) + .collect::>() + .map_err(|_| InnerError::InternalError)?; + Ok(Json(apps)) +} + +#[endpoint] +pub async fn get(id: PathParam) -> Result> { + let actor = APPS_ACTOR.get().ok_or(InnerError::Unavailable)?; + let app = call!(actor, |reply| AppsMsg::Get(id.into_inner().into(), reply)) + .map_err(InnerError::from)? + .map_err(InnerError::from)?; + let app = app.try_into().map_err(|_| InnerError::InternalError)?; + Ok(Json(app)) +} diff --git a/src/web/auth.rs b/src/web/auth.rs index e1284d8..accabe2 100644 --- a/src/web/auth.rs +++ b/src/web/auth.rs @@ -25,17 +25,20 @@ use salvo::{ use serde::{Deserialize, Serialize}; use serde_xml_rs::from_str; use snafu::{ErrorCompat, prelude::*}; -use surrealdb::{ - Surreal, - engine::local::Db, - sql::{Data, Operator, Value, statements::InsertStatement, to_value}, - syn::idiom, +use surrealdb::{Surreal, engine::local::Db}; +use surrealdb_core::sql::{ + AssignOperator, Idiom, Part, + data::{Assignment, Data}, + expression::Expr, + statements::InsertStatement, }; +use surrealdb_types::{SurrealValue, Value}; use tracing::{debug, error}; use crate::{ app_config::BiscuitConfig, - db::{UserID, model::User}, + db::{IUserID, UserID, model::InternalUser}, + steam::steam_user_actor::SteamUserMsg, }; static AUTH_ACTOR: OnceLock> = OnceLock::new(); @@ -95,7 +98,7 @@ impl From for StatusError { .unwrap_or_default() .to_string(); error.brief = value.to_string(); - error.detail = value.backtrace().map(std::string::ToString::to_string); + error.detail = value.backtrace().map(ToString::to_string); error } } @@ -192,8 +195,10 @@ pub async fn enforce_admin(depot: &mut Depot) -> Result<()> { None => Err(InnerError::Unauthorized)?, Some(userid) => { let actor = AUTH_ACTOR.get().cloned().ok_or(InnerError::InternalError)?; - let admin = call!(actor, |reply| { AuthMessage::IsAdmin(userid, reply) }) - .map_err(|_| InnerError::InternalError)??; + let admin = call!(actor, |reply| { + AuthMessage::IsAdmin(userid.into(), reply) + }) + .map_err(|_| InnerError::InternalError)??; if admin { Ok(()) @@ -211,12 +216,12 @@ pub async fn validate_opt(req: &mut Request, depot: &mut Depot) -> Result<()> { Ok(()) } /// Returns the user id of the current user, if any. -pub fn get_user_from_depot(depot: &mut Depot) -> Option { +pub fn get_user_from_depot(depot: &mut Depot) -> Option { let authorizer = depot.obtain_mut::().ok()?; - let (userid, _): (String, i64) = authorizer + let (userid, _): (i64, i64) = authorizer .query_exactly_one("data($user, 0) <- user($user)") .ok()?; - Some(userid) + Some(IUserID::from(userid)) } #[derive(Debug, Serialize, Deserialize, PartialEq)] @@ -242,19 +247,21 @@ pub enum AuthMessage { GetAuthUrl(String, RpcReplyPort), VerifySteamResponse(MultiMap, RpcReplyPort), ValidateToken(Cookie<'static>, RpcReplyPort>), - IsAdmin(String, RpcReplyPort>), + IsAdmin(IUserID, RpcReplyPort>), } pub struct AuthState { open_id_info: Info, database: Surreal, base_url: Arc, biscuit: Arc, + steam_user_actor_ref: ActorRef, } pub struct AuthArgs { pub database: Surreal, pub client: Client, pub base_url: Arc, pub biscuit: Arc, + pub steam_user_actor_ref: ActorRef, } #[async_trait] impl Actor for AuthActor { @@ -273,6 +280,7 @@ impl Actor for AuthActor { database: args.database, base_url: args.base_url.clone(), biscuit: args.biscuit.clone(), + steam_user_actor_ref: args.steam_user_actor_ref, }) } @@ -325,12 +333,12 @@ impl Actor for AuthActor { } impl AuthActor { - async fn is_admin(db: &Surreal, userid: String) -> Result { + async fn is_admin(db: &Surreal, userid: IUserID) -> Result { match db .query("SELECT admin FROM $user") - .bind(("user", UserID::from(userid).into_recordid())) + .bind(("user", userid)) .await - .map(surrealdb::Response::check) + .map(surrealdb::IndexedResults::check) { Err(_) | Ok(Err(_)) => Err(InnerError::InternalError)?, Ok(Ok(mut db_response)) => Ok(db_response.take("admin").ok().flatten() == Some(true)), @@ -490,27 +498,35 @@ impl AuthActor { .build(keypair) .map_err(|_| InnerError::PeerValidationFailed)?; + let Ok(user_id) = user_id.parse::() else { + return Err(InnerError::PeerValidationFailed)?; + }; + + let _ = state + .steam_user_actor_ref + .send_message(SteamUserMsg::Fetch(user_id.into())); + let based = biscuit .to_base64() .map_err(|_| InnerError::PeerValidationFailed)?; { - let user = User { - id: UserID::from(user_id.to_owned()).into_recordid(), + let user = InternalUser { + id: UserID::from(user_id).into(), admin: false, banned: false, last_logged_in: Utc::now(), }; - let mut stmt = InsertStatement::default(); - stmt.into = Some(Value::Table("users".into())); - stmt.data = Data::SingleExpression( - to_value(user.clone()).map_err(|_| InnerError::PeerValidationFailed)?, - ); - stmt.update = Some(Data::UpdateExpression(vec![( - idiom("last_logged_in").map_err(|_| InnerError::PeerValidationFailed)?, - Operator::Equal, - Utc::now().into(), - )])); + let stmt = InsertStatement { + into: Some(Expr::Table("users".into())), + data: Data::SingleExpression(Expr::from_public_value(user.clone().into_value())), + update: Some(Data::UpdateExpression(vec![Assignment { + place: Idiom(vec![Part::Field("last_logged_in".into())]), + operator: AssignOperator::Assign, + value: Expr::from_public_value(Value::Datetime(Utc::now().into())), + }])), + ..Default::default() + }; for (i, error) in state .database .query(stmt) diff --git a/src/web/item.rs b/src/web/item.rs index 7dceab9..2c3ba53 100644 --- a/src/web/item.rs +++ b/src/web/item.rs @@ -1,18 +1,26 @@ use std::sync::OnceLock; -use ractor::{Actor, ActorProcessingErr, ActorRef, RpcReplyPort, async_trait, call}; +use ractor::{async_trait, call, Actor, ActorProcessingErr, ActorRef, RpcReplyPort}; use salvo::{ - Depot, Writer, - oapi::{endpoint, extract::PathParam}, - prelude::{Json, StatusCode, StatusError}, + oapi::{endpoint, extract::PathParam}, prelude::{Json, StatusCode, StatusError}, + Depot, + Writer, }; -use surrealdb::{RecordId, Surreal, engine::local::Db}; -use tracing::{error, instrument}; +use surrealdb::{engine::local::Db, Surreal}; +use surrealdb_core::sql::{ + field::Selector, lookup::{LookupKind, LookupSubject}, part::DestructurePart, statements::SelectStatement, BinaryOperator, Closure, Dir, Expr, Field, Fields, Idiom, Kind, + Literal, + Lookup, + Param, + Part, +}; +use surrealdb_types::{RecordId, SurrealValue, ToSql}; +use tracing::{debug, error, instrument}; use crate::{ db::{ - UserID, - model::{FullWorkshopItem, WorkshopItem, into_string}, + model::{ExternalFullWorkshopItem, InternalFullWorkshopItem, Status}, IItemID, + IUserID, }, web::auth, }; @@ -62,9 +70,9 @@ pub struct ItemArgs { pub enum ItemMsg { Get( - String, - Option, - RpcReplyPort>, + IItemID, + Option, + RpcReplyPort>, ), } @@ -103,145 +111,153 @@ impl Actor for ItemActor { } } -// Core query logic extracted from the previous inline endpoint version. -async fn get_item(db: &Surreal, id: String, user: Option) -> Result { - let id = RecordId::from_table_key("workshop_items", &id); - let mut response = db - .query( - "SELECT in.appid as appid, in.description as description, in.id as id, in.title - as title, in.author as author, in.languages as languages, in.last_updated as - last_updated, in.score as score, in.tags.{id: id.to_string(), app_id, display_name} \ - as tags, in.preview_url as preview_url, [] as properties FROM \ - $id<-item_dependencies.*;", - ) - .query( - "SELECT out.appid as appid, out.description as description, out.id as id, - out.author as author, out.languages as languages, out.last_updated as - last_updated, out.title as title, out.score as score, out.tags.{id: id.to_string(), \ - app_id, display_name} as tags, out.preview_url as preview_url, [] as properties - FROM $id->item_dependencies.*;", - ) - .bind(("id", id.clone())) +async fn get_item( + db: &Surreal, + id: IItemID, + user: Option, +) -> Result { + let dep_fields = [ + DestructurePart::Field("app".to_string()), + DestructurePart::Field("author".to_string()), + DestructurePart::Field("description".to_string()), + DestructurePart::Field("id".to_string()), + DestructurePart::Field("languages".to_string()), + DestructurePart::Field("last_updated".to_string()), + DestructurePart::Field("preview_url".to_string()), + DestructurePart::Field("score".to_string()), + DestructurePart::Field("title".to_string()), + DestructurePart::All("tags".to_string()), + ]; + let mut stmt = SelectStatement::default(); + stmt.what = vec![Expr::from_public_value( + RecordId::from(id.clone()).into_value(), + )]; + + stmt.fields = Fields::Select(vec![ + Field::All, + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![Part::Field("tags".to_string()), Part::All])), + alias: None, + }), + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![Part::Field("author".to_string()), Part::All])), + alias: None, + }), + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![ + Part::Graph(Lookup { + kind: LookupKind::Graph(Dir::Out), + what: vec![LookupSubject::Table { + table: "workshop_item_properties".to_string(), + referencing_field: None, + }], + ..Default::default() + }), + Part::All, + ])), + // ToDo: Filter for user submitted props + alias: Some(Idiom(vec![ + Part::Field("properties".to_string()), + Part::Method( + "filter".to_string(), + vec![Expr::Closure(Box::new(Closure { + args: vec![(Param::new("prop".to_string()), Kind::Any)], + returns: None, + body: Expr::Binary { + left: Box::new(Expr::Idiom(Idiom(vec![ + Part::Start(Expr::Param(Param::new("prop".to_string()))), + Part::Field("status".to_string()), + ]))), + op: BinaryOperator::ExactEqual, + right: Box::new(Expr::Literal(Literal::Integer( + Status::Accepted as i64, + ))), + }, + }))], + ), + ])), + }), + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![ + Part::Graph(Lookup { + kind: LookupKind::Graph(Dir::Out), + what: vec![LookupSubject::Table { + table: "item_dependencies".to_string(), + referencing_field: None, + }], + ..Default::default() + }), + Part::All, + Part::Field("in".to_string()), + Part::All, + Part::Destructure(dep_fields.to_vec()), + ])), + alias: Some(Idiom::field("dependencies".to_string())), + }), + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![ + Part::Graph(Lookup { + kind: LookupKind::Graph(Dir::In), + what: vec![LookupSubject::Table { + table: "item_dependencies".to_string(), + referencing_field: None, + }], + ..Default::default() + }), + Part::All, + Part::Field("in".to_string()), + Part::All, + Part::Destructure(dep_fields.to_vec()), + ])), + alias: Some(Idiom::field("dependants".to_string())), + }), + ]); + + debug!(sql = stmt.to_sql(), "item query"); + + let result: Option = db + .query(stmt) + .bind(("id", RecordId::from(id))) .await + .inspect_err(|error| error!(message = "get_item", ?error, "Failed to query database")) + .map_err(|_| InnerError::InternalError)? + .take(0) + .inspect_err(|error| error!(message = "get_item", ?error, "Failed to take result")) .map_err(|_| InnerError::InternalError)?; - - let dependants: Vec> = - response.take(0).map_err(|_| InnerError::InternalError)?; - let dependencies: Vec> = - response.take(1).map_err(|_| InnerError::InternalError)?; - - let result = { - let mut res = match user { - None => db - .query( - r"SELECT *, tags.{id: id.to_string(), app_id, display_name} as tags, - ->workshop_item_properties.filter(|$prop|$prop.status == 1)[*].{ - id: id.to_string(), - in: in.to_string(), - out: out.id.{ - class, - `value` - }, - source: 'system', - status, - upvote_count, - vote_count - } as properties FROM $id", - ) - .bind(("id", id.clone())) - .await - .map_err(|_| InnerError::InternalError)?, - Some(user) => db - .query(format!( - "SELECT *, tags.{{id: id.to_string(), app_id, display_name}} as tags, - ->workshop_item_properties.filter(|$prop|$prop.status == 1 || \ - $prop.source == {})[*].{{ - id: id.to_string(), - in: in.to_string(), - out: out.id.{{ - class, - `value` - }}, - source: 'system', - status, - upvote_count, - vote_count, - vote_state: votes:{{item: $id, link: out, user: {0}}}.score - }} as properties FROM $id", - UserID::from(user).into_recordid() - )) - .bind(("id", id)) - .await - .map_err(|_| InnerError::InternalError)?, - }; - - let result: Option> = - res.take(0).map_err(|_| InnerError::InternalError)?; - result.ok_or(InnerError::NotFound)? - }; - - Ok(FullWorkshopItem { - appid: result.appid, - description: result.description, - id: into_string(result.id.key()), - title: result.title, - preview_url: result.preview_url, - languages: result.languages, - author: result.author, - last_updated: result.last_updated, - dependencies: dependencies - .into_iter() - .map(|e| FullWorkshopItem { - appid: e.appid, - author: e.author, - dependants: vec![], - dependencies: vec![], - description: e.description, - id: into_string(e.id.key()), - languages: e.languages, - title: e.title, - preview_url: e.preview_url, - last_updated: e.last_updated, - tags: e.tags, - score: e.score, - properties: e.properties, - }) - .collect(), - - dependants: dependants - .into_iter() - .map(|e| FullWorkshopItem { - appid: e.appid, - author: e.author, - dependants: vec![], - dependencies: vec![], - description: e.description, - id: into_string(e.id.key()), - languages: e.languages, - title: e.title, - preview_url: e.preview_url, - last_updated: e.last_updated, - tags: e.tags, - score: e.score, - properties: e.properties, - }) - .collect(), - tags: result.tags, - score: result.score, - properties: result.properties, - }) + result.ok_or(Error::from(InnerError::NotFound)) } /// GET /api/item/{id} /// Retrieves a full workshop item by id, including dependencies and dependants. #[endpoint] #[instrument(skip_all)] -pub async fn get(id: PathParam, depot: &mut Depot) -> Result> { +pub async fn get(id: PathParam, depot: &mut Depot) -> Result> { + // Lazily spawn the actor on first use and keep a global reference like auth.rs + let actor = ITEM_ACTOR.get().cloned().ok_or(InnerError::InternalError)?; + + let user = auth::get_user_from_depot(depot).map(Into::into); + let data = call!(actor, |reply| { ItemMsg::Get(id.0.into(), user, reply) }) + .map_err(|_| InnerError::InternalError)??; + Ok(Json( + data.try_into().map_err(|_| InnerError::InternalError)?, + )) +} + +/// GET /api/item/{id}/app +/// Retrieves the app +#[endpoint] +#[instrument(skip_all)] +pub async fn app_from_item( + id: PathParam, + depot: &mut Depot, +) -> Result> { // Lazily spawn the actor on first use and keep a global reference like auth.rs let actor = ITEM_ACTOR.get().cloned().ok_or(InnerError::InternalError)?; - let user = auth::get_user_from_depot(depot); - let data = call!(actor, |reply| { ItemMsg::Get(id.0, user, reply) }) + let user = auth::get_user_from_depot(depot).map(Into::into); + let data = call!(actor, |reply| { ItemMsg::Get(id.0.into(), user, reply) }) .map_err(|_| InnerError::InternalError)??; - Ok(Json(data)) + Ok(Json( + data.try_into().map_err(|_| InnerError::InternalError)?, + )) } diff --git a/src/web/mod.rs b/src/web/mod.rs index c8fbf56..a0d3f30 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,4 +1,5 @@ mod admin; +mod apps; pub mod auth; mod companions; pub mod item; @@ -28,9 +29,10 @@ pub async fn start(db: Surreal, config: Arc) { .hoop(max_size(1024 * 1024)) .push(Router::with_path("list").get(query::list)) .push( - Router::with_path("item/{id}") + Router::with_path("item") .hoop(auth::validate_opt) - .get(item::get), + .push(Router::with_path("{id}").get(item::get)) + .push(Router::with_path("{id}/app").get(item::get)), ) .push( Router::with_path("property") @@ -59,8 +61,12 @@ pub async fn start(db: Surreal, config: Arc) { Router::with_path("users") .get(admin::get_users) .put(admin::patch_user), - ), + ) + .push(Router::with_path("apps").get(apps::list).post(apps::upsert)) + .push(Router::with_path("app").delete(apps::remove)), ) + .push(Router::with_path("app/{id}").get(apps::get)) + .push(Router::with_path("apps").get(apps::list_available)) .hoop(affix_state::inject(config)) .push(Router::with_path("login").get(auth::redirect_to_steam_auth)) .push(Router::with_path("verify").get(auth::verify_token_from_steam)) diff --git a/src/web/properties.rs b/src/web/properties.rs index 3be60a1..4f6c3d2 100644 --- a/src/web/properties.rs +++ b/src/web/properties.rs @@ -8,10 +8,10 @@ use snafu::{ErrorCompat, prelude::*}; use crate::{ db::{ - model::{Source, Status}, + model::{ExternalSource, Status}, properties_actor::{PROPERTIES_ACTOR, PropertiesMsg}, }, - domain::properties::{NewProperty, PropertiesError, VoteData}, + domain::properties::{ExternalNewProperty, ExternalVoteData, PropertiesError}, web::auth, }; @@ -54,7 +54,7 @@ impl From for StatusError { .unwrap_or_default() .to_string(); error.brief = value.to_string(); - error.detail = value.backtrace().map(std::string::ToString::to_string); + error.detail = value.backtrace().map(ToString::to_string); error } } @@ -84,7 +84,7 @@ impl From for InnerError { /// Add or change a vote for a property. /// Property must exist; score must be either 1 or -1. #[endpoint] -pub async fn vote(vote_data: JsonBody, depot: &mut Depot) -> Result<()> { +pub async fn vote(vote_data: JsonBody, depot: &mut Depot) -> Result<()> { let Some(userid) = auth::get_user_from_depot(depot) else { return Err(InnerError::Unauthorized.into()); }; @@ -93,7 +93,7 @@ pub async fn vote(vote_data: JsonBody, depot: &mut Depot) -> Result<() .cloned() .ok_or(InnerError::InternalError)?; call!(actor, |reply| PropertiesMsg::Vote( - vote_data.0, + vote_data.0.into(), userid, reply )) @@ -104,7 +104,7 @@ pub async fn vote(vote_data: JsonBody, depot: &mut Depot) -> Result<() /// Remove a vote previously cast for a property by the current user. #[endpoint] -pub async fn remove(vote_data: JsonBody, depot: &mut Depot) -> Result<()> { +pub async fn remove(vote_data: JsonBody, depot: &mut Depot) -> Result<()> { let Some(userid) = auth::get_user_from_depot(depot) else { return Err(InnerError::Unauthorized.into()); }; @@ -113,8 +113,8 @@ pub async fn remove(vote_data: JsonBody, depot: &mut Depot) -> Result< .cloned() .ok_or(InnerError::InternalError)?; call!(actor, |reply| PropertiesMsg::Remove( - vote_data.0, - userid, + vote_data.0.into(), + userid.into(), reply )) .map_err(InnerError::from)? @@ -127,7 +127,7 @@ pub async fn remove(vote_data: JsonBody, depot: &mut Depot) -> Result< /// - Likeness checks are done on the value only using Damerau–Levenshtein /// distance. #[endpoint] -pub async fn new(new_property: JsonBody, depot: &mut Depot) -> Result<()> { +pub async fn new(new_property: JsonBody, depot: &mut Depot) -> Result<()> { let Some(userid) = auth::get_user_from_depot(depot) else { return Err(InnerError::Unauthorized.into()); }; @@ -135,9 +135,15 @@ pub async fn new(new_property: JsonBody, depot: &mut Depot) -> Resu .get() .cloned() .ok_or(InnerError::InternalError)?; + let source = ExternalSource::User( + userid + .try_into_external() + .map_err(|_| InnerError::InternalError)?, + ) + .into(); call!(actor, |reply| PropertiesMsg::NewProperty( - new_property.0, - Source::User(userid), + new_property.0.into(), + source, Status::Pending, reply, )) diff --git a/src/web/query.rs b/src/web/query.rs index f53abd2..c2dae31 100644 --- a/src/web/query.rs +++ b/src/web/query.rs @@ -1,275 +1,191 @@ -use std::str::FromStr; - -use itertools::Itertools; use salvo::{ - Request, Writer, - oapi::{endpoint, extract::QueryParam}, - prelude::Json, + oapi::{endpoint, extract::QueryParam}, prelude::Json, + Request, + Writer, }; use snafu::{ResultExt, Whatever}; -use surrealdb::{ - RecordId, Surreal, - engine::local::Db, - sql::{ - Cond, Expression, Field, Limit, Operator, Start, Value, idiom, statements::SelectStatement, - to_value, - }, +use surrealdb::{engine::local::Db, Surreal}; +use surrealdb_core::sql::{ + field::Selector, lookup::{LookupKind, LookupSubject}, order::{OrderList, Ordering}, part::DestructurePart, statements::SelectStatement, BinaryOperator, Closure, Cond, Dir, Expr, Field, Fields, + Idiom, Kind, Limit, Literal, Lookup, + Order, + Param, + Part, + RecordIdLit, + Start, }; -use tracing::{Instrument, info, info_span, instrument}; +use surrealdb_types::{RecordId, SurrealValue, Table, ToSql, Value}; +use tracing::{debug, info_span, instrument, Instrument}; use crate::{ - db::model::{OrderBy, WorkshopItem}, + db::{ + model::{ExternalWorkshopItem, InternalWorkshopItem, OrderBy, Status}, IAppID, + ITagID, + }, processing::language_actor::DetectedLanguage, web, web::DB_POOL, }; + +// ToDo: Seperate out filtering to its own struct +// And, handle pagination based on the last element for performance #[instrument(skip_all)] #[endpoint] pub async fn list( _: &mut Request, + app: QueryParam, page: QueryParam, limit: QueryParam, - languages: QueryParam, + language: QueryParam, mut tags: QueryParam, false>, mut title: QueryParam, - last_updated: QueryParam, + last_updated: QueryParam, mut order_by: QueryParam, -) -> web::Result>>> { +) -> web::Result>> { let page = page.unwrap_or(0); let limit = limit.unwrap_or(100).min(100); let db: &Surreal = DB_POOL.get().expect("Getting db connection"); #[instrument(skip_all)] async fn query( + app: i64, page: u64, limit: u64, - languages: Option, + language: Option, tags: Vec, title: Option, - last_updated: Option, + last_updated: Option, order_by: Option, db: &Surreal, - ) -> web::Result>, Whatever> { + ) -> web::Result, Whatever> { + let app = IAppID::from(app); let mut stmt = SelectStatement::default(); + stmt.what = vec![Expr::Table("workshop_items".into())]; { - stmt.expr.0.append(&mut vec![Field::All]); + stmt.fields = Fields::Select(vec![ + Field::All, + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![Part::Graph(Lookup { + kind: LookupKind::Graph(Dir::Out), + what: vec![LookupSubject::Table { + table: "workshop_item_properties".to_string(), + referencing_field: None, + }], + ..Default::default() + })])), + alias: Some(Idiom(vec![ + Part::Field("properties".to_string()), + Part::Method( + // ToDo: Filter for user submitted props + "filter".to_string(), + vec![Expr::Closure(Box::new(Closure { + args: vec![(Param::new("prop".to_string()), Kind::Any)], + returns: None, + body: Expr::Binary { + left: Box::new(Expr::Idiom(Idiom(vec![ + Part::Start(Expr::Param(Param::new("prop".to_string()))), + Part::Field("status".to_string()), + ]))), + op: BinaryOperator::ExactEqual, + right: Box::new(Expr::Literal(Literal::Integer( + Status::Accepted as i64, + ))), + }, + }))], + ), + ])), + }), + Field::Single(Selector { + expr: Expr::Idiom(Idiom(vec![Part::Field("tags".to_string()), Part::All])), + alias: None, + }) + ]); + } + stmt.limit = Some(Limit(Expr::from_public_value(limit.into_value()))); + stmt.start = Some(Start(Expr::from_public_value((page * limit).into_value()))); + stmt.cond = { + let mut conditions = vec![]; + conditions.push(Expr::Binary { + left: Box::new(Expr::Idiom(Idiom::field("app".to_string()))), + op: BinaryOperator::Equal, + right: Box::new(Expr::from_public_value(RecordId::from(app).into_value())), + }); - { - stmt.expr.0.push(Field::Single { - expr: idiom("tags.{id: id.to_string(), app_id, display_name}") - .expect("expanding tags idiom") - .into(), - alias: Some("tags".into()), + if let Some(language) = language { + conditions.push(Expr::Binary { + left: Box::new(Expr::Idiom(Idiom::field("language".to_string()))), + op: BinaryOperator::ContainAny, + right: Box::new(Expr::Literal(Literal::Integer(language as i64))), }); } - { - stmt.expr.0.push(Field::Single { - // Select _approved_ props only - expr: idiom( - r"->workshop_item_properties.filter(|$prop|$prop.status == 1)[*].{ - id: id.to_string(), - in: in.to_string(), - out: out.id.{ - class, - `value` - }, - source: 'system', - status, - upvote_count, - vote_count - }", - ) - .expect("expanding properties idiom") - .into(), - alias: Some("properties".into()), + + if !tags.is_empty() { + conditions.push(Expr::Binary { + left: Box::new(Expr::Idiom(Idiom::field("tags".to_string()))), + op: BinaryOperator::ContainAll, + right: Box::new(Expr::Literal(Literal::Array( + tags.into_iter() + .map(|tag| Expr::from_public_value(ITagID::from(tag).into_value())) + .collect::>(), + ))), }); } - if let Some(OrderBy::Dependents) = order_by { - stmt.expr.0.push(Field::Single { - expr: idiom(" <-item_dependencies.len()") - .expect("expanding item_tags idiom") - .into(), - alias: Some("dependencies_length".into()), + + if let Some(title) = title { + conditions.push(Expr::Binary { + left: Box::new(Expr::Idiom(Idiom::field("title".to_string()))), + op: BinaryOperator::Contain, + right: Box::new(Expr::Literal(Literal::String(title))), }); } - } - stmt.limit = Some({ - let mut d = Limit::default(); - d.0 = to_value(limit).whatever_context("limit")?; - d - }); - stmt.start = Some({ - let mut s = Start::default(); - s.0 = to_value(limit * page).whatever_context("start limit")?; - s - }); - - stmt.parallel = true; - stmt.what.0.push(Value::Table("workshop_items".into())); - stmt.cond = { - let conditions = vec![ - languages.map(|lang| { - Expression::new( - Value::Array(vec![(lang as u8).into(), Value::Number(0.into())].into()), - Operator::ContainAny, - Value::Idiom("languages".into()), - ) - }), - last_updated.map(|updated| { - Expression::new( - Value::Idiom("last_updated".into()), - Operator::MoreThanOrEqual, - Value::Number(updated.into()), - ) - }), - (!tags.is_empty()).then(|| { - if true { - // All - Expression::new( - Value::Idiom("tags".into()), - Operator::ContainAll, - Value::Array( - tags.iter() - .map(|tag| { - to_value( - RecordId::from_str(tag) - .unwrap_or(RecordId::from_table_key("tags", tag)), - ) - .unwrap() - }) - .collect::>() - .into(), - ), - ) - } else { - // Either (unsupported for now) - Expression::new( - Value::Idiom( - idiom(&format!( - "tags.any(|$var| {} )", - tags.into_iter() - .map(|tag| format!( - "$var.id == {}", - RecordId::from_str(&tag) - .unwrap_or(RecordId::from_table_key("tags", tag)) - )) - .join(" OR ") - )) - .unwrap(), - ), - Operator::Equal, - Value::Bool(true), - ) - } - }), - title.map(|title_query| { - Expression::new( - Value::Idiom("title".into()), - Operator::Like, - Value::Strand(title_query.into()), - ) - }), - ] - .into_iter() - .flatten() - .collect::>(); + if let Some(last_updated) = last_updated { + conditions.push(Expr::Binary { + left: Box::new(Expr::Idiom(Idiom::field("last_updated".to_string()))), + op: BinaryOperator::MoreThan, + right: Box::new(Expr::Literal(Literal::Integer(last_updated))), + }); + } - if conditions.is_empty() { - None + let first = conditions.pop().expect("Expected at least one condition to be present"); + if conditions.len() == 1 { + Some(Cond(first)) } else { - let mut values = Value::None; - for mut condition in &conditions.into_iter().chunks(2) { - let c1 = condition.next(); - let c2 = condition.next(); - match (values, c1, c2) { - (Value::None, Some(expr1), Some(expr2)) => { - values = Value::Expression(Box::from(Expression::new( - expr1.into(), - Operator::And, - expr2.into(), - ))); - } - (Value::None, Some(expr1), None) => { - values = Value::Expression(Box::from(expr1)); - } - (Value::Expression(old), Some(expr1), Some(expr2)) => { - values = Value::Expression(Box::from(Expression::new( - Value::Expression(old), - Operator::And, - Value::Expression(Box::from(Expression::new( - expr1.into(), - Operator::And, - expr2.into(), - ))), - ))); - } - (Value::Expression(old), Some(expr1), None) => { - values = Value::Expression(Box::from(Expression::new( - Value::Expression(old), - Operator::And, - expr1.into(), - ))); - } - (other, ..) => { - values = other; - } + Some(Cond(conditions.into_iter().fold(first, |old, next| { + Expr::Binary { + left: Box::new(old), + op: BinaryOperator::And, + right: Box::new(next), } - } - let mut cond = Cond::default(); - cond.0 = to_value(values).unwrap(); - Some(cond) + }))) } }; - // A horrendous hack for ordering, because, the types are not exposed. - stmt.order = order_by.map(|order_term| { - use serde_json::{Map, Value}; - use str_macro::str; - let terms = Map::from_iter([ - ( - str!("value"), - serde_json::to_value(idiom(order_term.column_name()).unwrap()).unwrap(), - ), - (str!("collate"), Value::Bool(false)), - (str!("numeric"), Value::Bool(false)), - (str!("direction"), Value::Bool(false)), - ]); - serde_json::from_value(Value::Object(Map::from_iter([( - str!("Order"), - Value::Array(vec![Value::Object(terms)]), - )]))) - .unwrap() + stmt.order = order_by.map(|order_by| { + Ordering::Order(OrderList(vec![Order { + value: Idiom::field(order_by.column_name().to_string()), + collate: false, + numeric: false, + direction: false, + }])) }); - stmt.parallel = true; - - info!("{stmt}"); + debug!(sql = stmt.to_sql(), "running big query"); let mut results = db.query(stmt).await.whatever_context("querying")?; - let results: Vec> = + let results: Vec = results.take(0).whatever_context("taking result")?; - Ok(results + results .into_iter() - .map(|res| WorkshopItem { - appid: res.appid, - author: res.author, - description: res.description, - id: res.id.key().to_string().replace("⟩", "").replace("⟨", ""), - languages: res.languages, - title: res.title, - preview_url: res.preview_url, - last_updated: res.last_updated, - tags: res.tags, - score: res.score, - properties: res.properties, - }) - .collect()) + .map(ExternalWorkshopItem::try_from) + .collect::>() + .whatever_context("converting internal to external") } let results = query( + app.into_inner(), page, limit, - *languages, + *language, tags.take().unwrap_or_default(), title.take(), *last_updated, diff --git a/taplo.toml b/taplo.toml new file mode 100644 index 0000000..32cd94e --- /dev/null +++ b/taplo.toml @@ -0,0 +1,5 @@ +# https://taplo.tamasfe.dev/configuration/formatter-options.html +[formatting] +reorder_keys = true +reorder_arrays = true +reorder_inline_tables = true \ No newline at end of file diff --git a/ui/package-lock.json b/ui/package-lock.json index bdeb6e5..357b29e 100644 --- a/ui/package-lock.json +++ b/ui/package-lock.json @@ -21,11 +21,11 @@ "@eslint/js": "^9.18.0", "@inlang/cli": "^3.0.0", "@inlang/paraglide-js": "2.0.13", - "@skeletonlabs/skeleton": "^3.1.2", - "@skeletonlabs/skeleton-svelte": "^1.2.1", + "@skeletonlabs/skeleton": "^4.0.0", + "@skeletonlabs/skeleton-svelte": "^4.0.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/kit": "^2.16.0", - "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@sveltejs/kit": "^2.58.0", + "@sveltejs/vite-plugin-svelte": "^6.2.4", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", "@tailwindcss/vite": "^4.0.0", @@ -39,12 +39,12 @@ "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.3", "prettier-plugin-tailwindcss": "^0.6.11", - "svelte": "^5.0.0", + "svelte": "5.53.5", "svelte-check": "^4.0.0", "tailwindcss": "^4.0.0", "typescript": "^5.0.0", "typescript-eslint": "^8.20.0", - "vite": "^6.3.3", + "vite": "^6.4.2", "vitest": "^3.0.0" } }, @@ -59,6 +59,7 @@ "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, "license": "Apache-2.0", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", @@ -232,10 +233,44 @@ "node": ">=18" } }, + "node_modules/@emnapi/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.10.0.tgz", + "integrity": "sha512-yq6OkJ4p82CAfPl0u9mQebQHKPJkY7WrIuk205cTYnYe+k2Z8YBh11FrbRG/H6ihirqcacOgl2BIO8oyMQLeXw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.2.1", + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/runtime": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.10.0.tgz", + "integrity": "sha512-ewvYlk86xUoGI0zQRNq/mC+16R1QeDlKQy21Ki3oSYXNgLb45GV1P6A0M+/s6nyCuNDqe5VpaY84BzXGwVbwFA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@emnapi/wasi-threads": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.1.tgz", + "integrity": "sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.5.tgz", - "integrity": "sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", "cpu": [ "ppc64" ], @@ -250,9 +285,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.5.tgz", - "integrity": "sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", "cpu": [ "arm" ], @@ -267,9 +302,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.5.tgz", - "integrity": "sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", "cpu": [ "arm64" ], @@ -284,9 +319,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.5.tgz", - "integrity": "sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", "cpu": [ "x64" ], @@ -301,9 +336,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.5.tgz", - "integrity": "sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", "cpu": [ "arm64" ], @@ -318,9 +353,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.5.tgz", - "integrity": "sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", "cpu": [ "x64" ], @@ -335,9 +370,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.5.tgz", - "integrity": "sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", "cpu": [ "arm64" ], @@ -352,9 +387,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.5.tgz", - "integrity": "sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", "cpu": [ "x64" ], @@ -369,9 +404,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.5.tgz", - "integrity": "sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", "cpu": [ "arm" ], @@ -386,9 +421,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.5.tgz", - "integrity": "sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", "cpu": [ "arm64" ], @@ -403,9 +438,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.5.tgz", - "integrity": "sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", "cpu": [ "ia32" ], @@ -420,9 +455,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.5.tgz", - "integrity": "sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", "cpu": [ "loong64" ], @@ -437,9 +472,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.5.tgz", - "integrity": "sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", "cpu": [ "mips64el" ], @@ -454,9 +489,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.5.tgz", - "integrity": "sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", "cpu": [ "ppc64" ], @@ -471,9 +506,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.5.tgz", - "integrity": "sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", "cpu": [ "riscv64" ], @@ -488,9 +523,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.5.tgz", - "integrity": "sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", "cpu": [ "s390x" ], @@ -505,9 +540,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.5.tgz", - "integrity": "sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", "cpu": [ "x64" ], @@ -522,9 +557,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.5.tgz", - "integrity": "sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", "cpu": [ "arm64" ], @@ -539,9 +574,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.5.tgz", - "integrity": "sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", "cpu": [ "x64" ], @@ -556,9 +591,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.5.tgz", - "integrity": "sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", "cpu": [ "arm64" ], @@ -573,9 +608,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.5.tgz", - "integrity": "sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", "cpu": [ "x64" ], @@ -589,10 +624,27 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.5.tgz", - "integrity": "sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", "cpu": [ "x64" ], @@ -607,9 +659,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.5.tgz", - "integrity": "sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", "cpu": [ "arm64" ], @@ -624,9 +676,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.5.tgz", - "integrity": "sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", "cpu": [ "ia32" ], @@ -641,9 +693,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.5.tgz", - "integrity": "sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", "cpu": [ "x64" ], @@ -830,30 +882,30 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.1.tgz", - "integrity": "sha512-azI0DrjMMfIug/ExbBaeDVJXcY0a7EPvPjb2xAJPa4HeimBX+Z18HK8QQR3jb6356SnDDdxx+hinMLcJEDdOjw==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.9" + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/dom": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.1.tgz", - "integrity": "sha512-cwsmW/zyw5ltYTUeeYJ60CnQuPqmGwuGVhG9w0PRaRKkAyi38BT5CKrpIbb+jtahSwUl04cWzSx9ZOIxeS6RsQ==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.7.1", - "@floating-ui/utils": "^0.2.9" + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/utils": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.9.tgz", - "integrity": "sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==", + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", "dev": true, "license": "MIT" }, @@ -1020,9 +1072,9 @@ } }, "node_modules/@internationalized/date": { - "version": "3.8.2", - "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.8.2.tgz", - "integrity": "sha512-/wENk7CbvLbkUvX1tu0mwq49CVkkWpkXubGel6birjRPyo6uQ4nQpnq5xZu823zRCwwn82zgHrvgF1vZyvmVgA==", + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/@internationalized/date/-/date-3.12.0.tgz", + "integrity": "sha512-/PyIMzK29jtXaGU23qTvNZxvBXRtKbNnGDFD+PY6CZw/Y8Ex8pFUzkuCJCG9aOqmShjqhS9mPqP6Dk5onQY8rQ==", "license": "Apache-2.0", "dependencies": { "@swc/helpers": "^0.5.0" @@ -1055,6 +1107,16 @@ "node": ">=6.0.0" } }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", @@ -1074,9 +1136,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { @@ -1161,9 +1223,9 @@ "license": "MIT" }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.42.0.tgz", - "integrity": "sha512-gldmAyS9hpj+H6LpRNlcjQWbuKUtb94lodB9uCz71Jm+7BxK1VIOo7y62tZZwxhA7j1ylv/yQz080L5WkS+LoQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.2.tgz", + "integrity": "sha512-dnlp69efPPg6Uaw2dVqzWRfAWRnYVb1XJ8CyyhIbZeaq4CA5/mLeZ1IEt9QqQxmbdvagjLIm2ZL8BxXv5lH4Yw==", "cpu": [ "arm" ], @@ -1175,9 +1237,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.42.0.tgz", - "integrity": "sha512-bpRipfTgmGFdCZDFLRvIkSNO1/3RGS74aWkJJTFJBH7h3MRV4UijkaEUeOMbi9wxtxYmtAbVcnMtHTPBhLEkaw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.60.2.tgz", + "integrity": "sha512-OqZTwDRDchGRHHm/hwLOL7uVPB9aUvI0am/eQuWMNyFHf5PSEQmyEeYYheA0EPPKUO/l0uigCp+iaTjoLjVoHg==", "cpu": [ "arm64" ], @@ -1189,9 +1251,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.42.0.tgz", - "integrity": "sha512-JxHtA081izPBVCHLKnl6GEA0w3920mlJPLh89NojpU2GsBSB6ypu4erFg/Wx1qbpUbepn0jY4dVWMGZM8gplgA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.60.2.tgz", + "integrity": "sha512-UwRE7CGpvSVEQS8gUMBe1uADWjNnVgP3Iusyda1nSRwNDCsRjnGc7w6El6WLQsXmZTbLZx9cecegumcitNfpmA==", "cpu": [ "arm64" ], @@ -1203,9 +1265,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.42.0.tgz", - "integrity": "sha512-rv5UZaWVIJTDMyQ3dCEK+m0SAn6G7H3PRc2AZmExvbDvtaDc+qXkei0knQWcI3+c9tEs7iL/4I4pTQoPbNL2SA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.60.2.tgz", + "integrity": "sha512-gjEtURKLCC5VXm1I+2i1u9OhxFsKAQJKTVB8WvDAHF+oZlq0GTVFOlTlO1q3AlCTE/DF32c16ESvfgqR7343/g==", "cpu": [ "x64" ], @@ -1217,9 +1279,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.42.0.tgz", - "integrity": "sha512-fJcN4uSGPWdpVmvLuMtALUFwCHgb2XiQjuECkHT3lWLZhSQ3MBQ9pq+WoWeJq2PrNxr9rPM1Qx+IjyGj8/c6zQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.60.2.tgz", + "integrity": "sha512-Bcl6CYDeAgE70cqZaMojOi/eK63h5Me97ZqAQoh77VPjMysA/4ORQBRGo3rRy45x4MzVlU9uZxs8Uwy7ZaKnBw==", "cpu": [ "arm64" ], @@ -1231,9 +1293,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.42.0.tgz", - "integrity": "sha512-CziHfyzpp8hJpCVE/ZdTizw58gr+m7Y2Xq5VOuCSrZR++th2xWAz4Nqk52MoIIrV3JHtVBhbBsJcAxs6NammOQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.60.2.tgz", + "integrity": "sha512-LU+TPda3mAE2QB0/Hp5VyeKJivpC6+tlOXd1VMoXV/YFMvk/MNk5iXeBfB4MQGRWyOYVJ01625vjkr0Az98OJQ==", "cpu": [ "x64" ], @@ -1245,13 +1307,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.42.0.tgz", - "integrity": "sha512-UsQD5fyLWm2Fe5CDM7VPYAo+UC7+2Px4Y+N3AcPh/LdZu23YcuGPegQly++XEVaC8XUTFVPscl5y5Cl1twEI4A==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.60.2.tgz", + "integrity": "sha512-2QxQrM+KQ7DAW4o22j+XZ6RKdxjLD7BOWTP0Bv0tmjdyhXSsr2Ul1oJDQqh9Zf5qOwTuTc7Ek83mOFaKnodPjg==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1259,13 +1324,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.42.0.tgz", - "integrity": "sha512-/i8NIrlgc/+4n1lnoWl1zgH7Uo0XK5xK3EDqVTf38KvyYgCU/Rm04+o1VvvzJZnVS5/cWSd07owkzcVasgfIkQ==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.60.2.tgz", + "integrity": "sha512-TbziEu2DVsTEOPif2mKWkMeDMLoYjx95oESa9fkQQK7r/Orta0gnkcDpzwufEcAO2BLBsD7mZkXGFqEdMRRwfw==", "cpu": [ "arm" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1273,13 +1341,16 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.42.0.tgz", - "integrity": "sha512-eoujJFOvoIBjZEi9hJnXAbWg+Vo1Ov8n/0IKZZcPZ7JhBzxh2A+2NFyeMZIRkY9iwBvSjloKgcvnjTbGKHE44Q==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.60.2.tgz", + "integrity": "sha512-bO/rVDiDUuM2YfuCUwZ1t1cP+/yqjqz+Xf2VtkdppefuOFS2OSeAfgafaHNkFn0t02hEyXngZkxtGqXcXwO8Rg==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1287,41 +1358,84 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.42.0.tgz", - "integrity": "sha512-/3NrcOWFSR7RQUQIuZQChLND36aTU9IYE4j+TB40VU78S+RA0IiqHR30oSh6P1S9f9/wVOenHQnacs/Byb824g==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.60.2.tgz", + "integrity": "sha512-hr26p7e93Rl0Za+JwW7EAnwAvKkehh12BU1Llm9Ykiibg4uIr2rbpxG9WCf56GuvidlTG9KiiQT/TXT1yAWxTA==", "cpu": [ "arm64" ], "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.60.2.tgz", + "integrity": "sha512-pOjB/uSIyDt+ow3k/RcLvUAOGpysT2phDn7TTUB3n75SlIgZzM6NKAqlErPhoFU+npgY3/n+2HYIQVbF70P9/A==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.42.0.tgz", - "integrity": "sha512-O8AplvIeavK5ABmZlKBq9/STdZlnQo7Sle0LLhVA7QT+CiGpNVe197/t8Aph9bhJqbDVGCHpY2i7QyfEDDStDg==", + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.60.2.tgz", + "integrity": "sha512-2/w+q8jszv9Ww1c+6uJT3OwqhdmGP2/4T17cu8WuwyUuuaCDDJ2ojdyYwZzCxx0GcsZBhzi3HmH+J5pZNXnd+Q==", "cpu": [ "loong64" ], "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.60.2.tgz", + "integrity": "sha512-11+aL5vKheYgczxtPVVRhdptAM2H7fcDR5Gw4/bTcteuZBlH4oP9f5s9zYO9aGZvoGeBpqXI/9TZZihZ609wKw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.42.0.tgz", - "integrity": "sha512-6Qb66tbKVN7VyQrekhEzbHRxXXFFD8QKiFAwX5v9Xt6FiJ3BnCVBuyBxa2fkFGqxOCSGGYNejxd8ht+q5SnmtA==", + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.60.2.tgz", + "integrity": "sha512-i16fokAGK46IVZuV8LIIwMdtqhin9hfYkCh8pf8iC3QU3LpwL+1FSFGej+O7l3E/AoknL6Dclh2oTdnRMpTzFQ==", "cpu": [ "ppc64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1329,13 +1443,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.42.0.tgz", - "integrity": "sha512-KQETDSEBamQFvg/d8jajtRwLNBlGc3aKpaGiP/LvEbnmVUKlFta1vqJqTrvPtsYsfbE/DLg5CC9zyXRX3fnBiA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.60.2.tgz", + "integrity": "sha512-49FkKS6RGQoriDSK/6E2GkAsAuU5kETFCh7pG4yD/ylj9rKhTmO3elsnmBvRD4PgJPds5W2PkhC82aVwmUcJ7A==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1343,13 +1460,16 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.42.0.tgz", - "integrity": "sha512-qMvnyjcU37sCo/tuC+JqeDKSuukGAd+pVlRl/oyDbkvPJ3awk6G6ua7tyum02O3lI+fio+eM5wsVd66X0jQtxw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.60.2.tgz", + "integrity": "sha512-mjYNkHPfGpUR00DuM1ZZIgs64Hpf4bWcz9Z41+4Q+pgDx73UwWdAYyf6EG/lRFldmdHHzgrYyge5akFUW0D3mQ==", "cpu": [ "riscv64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ @@ -1357,13 +1477,16 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.42.0.tgz", - "integrity": "sha512-I2Y1ZUgTgU2RLddUHXTIgyrdOwljjkmcZ/VilvaEumtS3Fkuhbw4p4hgHc39Ypwvo2o7sBFNl2MquNvGCa55Iw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.60.2.tgz", + "integrity": "sha512-ALyvJz965BQk8E9Al/JDKKDLH2kfKFLTGMlgkAbbYtZuJt9LU8DW3ZoDMCtQpXAltZxwBHevXz5u+gf0yA0YoA==", "cpu": [ "s390x" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1371,13 +1494,16 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.42.0.tgz", - "integrity": "sha512-Gfm6cV6mj3hCUY8TqWa63DB8Mx3NADoFwiJrMpoZ1uESbK8FQV3LXkhfry+8bOniq9pqY1OdsjFWNsSbfjPugw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.60.2.tgz", + "integrity": "sha512-UQjrkIdWrKI626Du8lCQ6MJp/6V1LAo2bOK9OTu4mSn8GGXIkPXk/Vsp4bLHCd9Z9Iz2OTEaokUE90VweJgIYQ==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "glibc" + ], "license": "MIT", "optional": true, "os": [ @@ -1385,23 +1511,54 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.42.0.tgz", - "integrity": "sha512-g86PF8YZ9GRqkdi0VoGlcDUb4rYtQKyTD1IVtxxN4Hpe7YqLBShA7oHMKU6oKTCi3uxwW4VkIGnOaH/El8de3w==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.60.2.tgz", + "integrity": "sha512-bTsRGj6VlSdn/XD4CGyzMnzaBs9bsRxy79eTqTCBsA8TMIEky7qg48aPkvJvFe1HyzQ5oMZdg7AnVlWQSKLTnw==", "cpu": [ "x64" ], "dev": true, + "libc": [ + "musl" + ], "license": "MIT", "optional": true, "os": [ "linux" ] }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.60.2.tgz", + "integrity": "sha512-6d4Z3534xitaA1FcMWP7mQPq5zGwBmGbhphh2DwaA1aNIXUu3KTOfwrWpbwI4/Gr0uANo7NTtaykFyO2hPuFLg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.60.2.tgz", + "integrity": "sha512-NetAg5iO2uN7eB8zE5qrZ3CSil+7IJt4WDFLcC75Ymywq1VZVD6qJ6EvNLjZ3rEm6gB7XW5JdT60c6MN35Z85Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.42.0.tgz", - "integrity": "sha512-+axkdyDGSp6hjyzQ5m1pgcvQScfHnMCcsXkx8pTgy/6qBmWVhtRVlgxjWwDp67wEXXUr0x+vD6tp5W4x6V7u1A==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.60.2.tgz", + "integrity": "sha512-NCYhOotpgWZ5kdxCZsv6Iudx0wX8980Q/oW4pNFNihpBKsDbEA1zpkfxJGC0yugsUuyDZ7gL37dbzwhR0VI7pQ==", "cpu": [ "arm64" ], @@ -1413,9 +1570,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.42.0.tgz", - "integrity": "sha512-F+5J9pelstXKwRSDq92J0TEBXn2nfUrQGg+HK1+Tk7VOL09e0gBqUHugZv7SW4MGrYj41oNCUe3IKCDGVlis2g==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.60.2.tgz", + "integrity": "sha512-RXsaOqXxfoUBQoOgvmmijVxJnW2IGB0eoMO7F8FAjaj0UTywUO/luSqimWBJn04WNgUkeNhh7fs7pESXajWmkg==", "cpu": [ "ia32" ], @@ -1426,10 +1583,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.60.2.tgz", + "integrity": "sha512-qdAzEULD+/hzObedtmV6iBpdL5TIbKVztGiK7O3/KYSf+HIzU257+MX1EXJcyIiDbMAqmbwaufcYPvyRryeZtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.42.0.tgz", - "integrity": "sha512-LpHiJRwkaVz/LqjHjK8LCi8osq7elmpwujwbXKNW88bM8eeGxavJIKKjkjpMHAh/2xfnrt1ZSnhTv41WYUHYmA==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.2.tgz", + "integrity": "sha512-Nd/SgG27WoA9e+/TdK74KnHz852TLa94ovOYySo/yMPuTmpckK/jIF2jSwS3g7ELSKXK13/cVdmg1Z/DaCWKxA==", "cpu": [ "x64" ], @@ -1448,41 +1619,61 @@ "license": "MIT" }, "node_modules/@skeletonlabs/skeleton": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton/-/skeleton-3.1.3.tgz", - "integrity": "sha512-ZXllVGa5DoDQYeQF2866kKTGllRM11W0gRzvsDx8hiVE2Vj7Z0Z8dcOKOx+gb0myXG1PRAP5Yj7nwTLBDG14lg==", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton/-/skeleton-4.15.2.tgz", + "integrity": "sha512-5O23Py76nw56aoieV2b2T7MJ6xS0DwDjUULpwLnCXxXOnmzADEoWoQxb/ABbqg04IMOygtRzK3HO22I1+kFsog==", "dev": true, "license": "MIT", "peerDependencies": { "tailwindcss": "^4.0.0" } }, + "node_modules/@skeletonlabs/skeleton-common": { + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton-common/-/skeleton-common-4.15.2.tgz", + "integrity": "sha512-y7KZn++Av8UHdoeaaguQ7zIS1HlK7Y5jyPDnHy65wJ60iS97fMtQV0kGhqVoYCWhor+xrjbAFjWtaPOPPDEMYA==", + "dev": true, + "license": "MIT" + }, "node_modules/@skeletonlabs/skeleton-svelte": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton-svelte/-/skeleton-svelte-1.2.3.tgz", - "integrity": "sha512-0AwsLNoHyo71IE28KztjgXR8uxQKPkAkCT9LEhIRyeZJV+FC+PLS2+TAlnUEPfRLHhGJbkVu/5FJaFVCA/KoTw==", - "dev": true, - "dependencies": { - "@zag-js/accordion": "^1.7.0", - "@zag-js/avatar": "^1.7.0", - "@zag-js/combobox": "^1.7.0", - "@zag-js/dialog": "^1.7.0", - "@zag-js/file-upload": "^1.7.0", - "@zag-js/pagination": "^1.7.0", - "@zag-js/popover": "^1.7.0", - "@zag-js/progress": "^1.7.0", - "@zag-js/radio-group": "^1.7.0", - "@zag-js/rating-group": "^1.7.0", - "@zag-js/slider": "^1.7.0", - "@zag-js/svelte": "^1.7.0", - "@zag-js/switch": "^1.7.0", - "@zag-js/tabs": "^1.7.0", - "@zag-js/tags-input": "^1.7.0", - "@zag-js/toast": "^1.7.0", - "@zag-js/tooltip": "^1.7.0" + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/@skeletonlabs/skeleton-svelte/-/skeleton-svelte-4.15.2.tgz", + "integrity": "sha512-vZkRhR701EOHVXVKh/NFRSY8D9LPBvmdNFdtfgqO7TEg77sypJUvERl2dxErTLY1QjVklVpjsHRCTaSLn+1Ntg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@internationalized/date": "3.12.0", + "@skeletonlabs/skeleton-common": "4.15.2", + "@zag-js/accordion": "1.39.1", + "@zag-js/avatar": "1.39.1", + "@zag-js/carousel": "1.39.1", + "@zag-js/collapsible": "1.39.1", + "@zag-js/collection": "1.39.1", + "@zag-js/combobox": "1.39.1", + "@zag-js/date-picker": "1.39.1", + "@zag-js/dialog": "1.39.1", + "@zag-js/file-upload": "1.39.1", + "@zag-js/floating-panel": "1.39.1", + "@zag-js/listbox": "1.39.1", + "@zag-js/menu": "1.39.1", + "@zag-js/pagination": "1.39.1", + "@zag-js/popover": "1.39.1", + "@zag-js/progress": "1.39.1", + "@zag-js/radio-group": "1.39.1", + "@zag-js/rating-group": "1.39.1", + "@zag-js/slider": "1.39.1", + "@zag-js/steps": "1.39.1", + "@zag-js/svelte": "1.39.1", + "@zag-js/switch": "1.39.1", + "@zag-js/tabs": "1.39.1", + "@zag-js/tags-input": "1.39.1", + "@zag-js/toast": "1.39.1", + "@zag-js/toggle-group": "1.39.1", + "@zag-js/tooltip": "1.39.1", + "@zag-js/tree-view": "1.39.1" }, "peerDependencies": { - "svelte": "^5.20.0" + "svelte": "^5.29.0" } }, "node_modules/@sqlite.org/sqlite-wasm": { @@ -1495,6 +1686,13 @@ "sqlite-wasm": "bin/index.js" } }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@sveltejs/acorn-typescript": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.5.tgz", @@ -1515,23 +1713,23 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.21.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.21.2.tgz", - "integrity": "sha512-EMYTY4+rNa7TaRZYzCqhQslEkACEZzWc363jOYuc90oJrgvlWTcgqTxcGSIJim48hPaXwYlHyatRnnMmTFf5tA==", + "version": "2.58.0", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.58.0.tgz", + "integrity": "sha512-kT9GCN8yJTkCK1W+Gi/bvGooWAM7y7WXP+yd+rf6QOIjyoK1ERPrMwSufXJUNu2pMWIqruhFvmz+LbOqsEmKmA==", "dev": true, "license": "MIT", "dependencies": { + "@standard-schema/spec": "^1.0.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/cookie": "^0.6.0", "acorn": "^8.14.1", "cookie": "^0.6.0", - "devalue": "^5.1.0", + "devalue": "^5.6.4", "esm-env": "^1.2.2", "kleur": "^4.1.5", "magic-string": "^0.30.5", "mrmime": "^2.0.0", - "sade": "^1.8.1", - "set-cookie-parser": "^2.6.0", + "set-cookie-parser": "^3.0.0", "sirv": "^3.0.0" }, "bin": { @@ -1541,49 +1739,58 @@ "node": ">=18.13" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0", + "@opentelemetry/api": "^1.0.0", + "@sveltejs/vite-plugin-svelte": "^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0 || ^7.0.0", "svelte": "^4.0.0 || ^5.0.0-next.0", - "vite": "^5.0.3 || ^6.0.0" + "typescript": "^5.3.3 || ^6.0.0", + "vite": "^5.0.3 || ^6.0.0 || ^7.0.0-beta.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@opentelemetry/api": { + "optional": true + }, + "typescript": { + "optional": true + } } }, "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-5.1.0.tgz", - "integrity": "sha512-wojIS/7GYnJDYIg1higWj2ROA6sSRWvcR1PO/bqEyFr/5UZah26c8Cz4u0NaqjPeVltzsVpt2Tm8d2io0V+4Tw==", + "version": "6.2.4", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.4.tgz", + "integrity": "sha512-ou/d51QSdTyN26D7h6dSpusAKaZkAiGM55/AKYi+9AGZw7q85hElbjK3kEyzXHhLSnRISHOYzVge6x0jRZ7DXA==", "dev": true, "license": "MIT", "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^4.0.1", - "debug": "^4.4.1", + "@sveltejs/vite-plugin-svelte-inspector": "^5.0.0", "deepmerge": "^4.3.1", - "kleur": "^4.1.5", - "magic-string": "^0.30.17", - "vitefu": "^1.0.6" + "magic-string": "^0.30.21", + "obug": "^2.1.0", + "vitefu": "^1.1.1" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" + "node": "^20.19 || ^22.12 || >=24" }, "peerDependencies": { "svelte": "^5.0.0", - "vite": "^6.0.0" + "vite": "^6.3.0 || ^7.0.0" } }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-4.0.1.tgz", - "integrity": "sha512-J/Nmb2Q2y7mck2hyCX4ckVHcR5tu2J+MtBEQqpDrrgELZ2uvraQcK/ioCV61AqkdXFgriksOKIceDcQmqnGhVw==", + "node_modules/@sveltejs/vite-plugin-svelte/node_modules/@sveltejs/vite-plugin-svelte-inspector": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.2.tgz", + "integrity": "sha512-TZzRTcEtZffICSAoZGkPSl6Etsj2torOVrx6Uw0KpXxrec9Gg6jFWQ60Q3+LmNGfZSxHRCZL7vXVZIWmuV50Ig==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^4.3.7" + "obug": "^2.1.0" }, "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22" + "node": "^20.19 || ^22.12 || >=24" }, "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@sveltejs/vite-plugin-svelte": "^6.0.0-next.0", "svelte": "^5.0.0", - "vite": "^6.0.0" + "vite": "^6.3.0 || ^7.0.0" } }, "node_modules/@swc/helpers": { @@ -2046,6 +2253,12 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT" + }, "node_modules/@typescript-eslint/eslint-plugin": { "version": "8.33.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz", @@ -2196,7 +2409,7 @@ "version": "8.33.1", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz", "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2320,33 +2533,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vitest/mocker": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", - "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.2.2", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, "node_modules/@vitest/pretty-format": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.2.tgz", @@ -2418,326 +2604,472 @@ } }, "node_modules/@zag-js/accordion": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.15.0.tgz", - "integrity": "sha512-EKNeuKx+lOQ/deCe/ApCjVPxpxpDwT2NXvMPL+YvqXmSv7hAnTLs9fDKjbDUQUMmsyx32BsBd8t6d17DL3rPXg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/accordion/-/accordion-1.39.1.tgz", + "integrity": "sha512-GA3m7gRTm3weSe1eMlHIsTNztcjZ6joIaRgxxKil7q/UX0xIVVGDy0aCr6oo7FAuoMiOOBVurYXILpFZ30nOXA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/anatomy": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.15.0.tgz", - "integrity": "sha512-r0l5I7mSsF35HdwXm22TppNhfVftFuqvKfHvTUw+wQZhni4eUL93HypJD0Fl7mDhtP5zfVGfBwR048OzD0+tCw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/anatomy/-/anatomy-1.39.1.tgz", + "integrity": "sha512-p2iFAs2pVQgv5iCDAftA7g9Z/fUYXW94dRIGk415TSbkp/YDENydm/JtRoNctp302UIx4Eeuc5QBR+7h5kuISA==", "dev": true, "license": "MIT" }, "node_modules/@zag-js/aria-hidden": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.15.0.tgz", - "integrity": "sha512-3ogglAasycekTHI34ph16mqwM+VtHCOMtrFHWzPwB16itV5oDEeeMNdQXenHSSyQ/07nJ2QsRGFFjGhPm1kWNg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/aria-hidden/-/aria-hidden-1.39.1.tgz", + "integrity": "sha512-wiwcz3N086qBMEU3VKfHhcvGm6Jm1PIcDXys/jEqiKPtHoYZhDip0n0cPOoasss/A1oS39QFVdk3WpLXGu3Izw==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.39.1" + } }, "node_modules/@zag-js/auto-resize": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.15.0.tgz", - "integrity": "sha512-EXgrsU7OWxc7obSOt8Okh0144H8DQi1S84OsOUY04Uni11Dnp5/X8+t6mvBbkw4/Qyz5UBjChjocwBcO+HHV8w==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/auto-resize/-/auto-resize-1.39.1.tgz", + "integrity": "sha512-ditIo9mW7fapq+4yx3/8hMpMZlWaoOy66EOzUz8dSVqnxnTWAjnTICu/9zFh8pkWerlzGTtDOJPP1oZ8S/rgVg==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.39.1" } }, "node_modules/@zag-js/avatar": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.15.0.tgz", - "integrity": "sha512-EHGxzXb1mLf3n6x0z/rqFl1mghDB/gyfPAeaFUoA/cacmmMk8YB3aDUXkS9pTgN9stYJBM5f6T4xB1ZUhrP8tg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/avatar/-/avatar-1.39.1.tgz", + "integrity": "sha512-LWrgJ0bebnXPSL+uehA9z6BlCD/MZEOQBJqH/F2QQFSAAZXUUDKtzVDmc+UtwjDsHXqqTghi+v2atQJHNMcJ2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/carousel": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/carousel/-/carousel-1.39.1.tgz", + "integrity": "sha512-5z5z3IldUgZ/R+KZLNQDoJFNTXzYd28YOmgfWH61Vvyv+RarX8kwZW8ajW/fNiqcWXyhW3/VMU0lArrfjbQVtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/scroll-snap": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/collapsible": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/collapsible/-/collapsible-1.39.1.tgz", + "integrity": "sha512-Zgccg/t7M8i0JVwZPPgW7XB7kGhTO475hsmwkF/8CYLqBBckVDHUARp2we24hENCm/98eez6R0eDEmE+tldFWA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/collection": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.15.0.tgz", - "integrity": "sha512-oC3i6c/oP/FuNPsfgoC1reSXbAvDBGXl0HU3CcvXiNLHbjg2ek8J7kbow6MNuXK6chiksiOHbzKxHl2Oo0Ox7A==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/collection/-/collection-1.39.1.tgz", + "integrity": "sha512-fyOyKmP7MRo0/U8mBmB7KgHRXHhXP27LCcasy3x+qTAQtuEfYG1EPhKuj07oBWlX/2qfcKYn2R3YopHcqFcCiA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/utils": "1.15.0" + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/combobox": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.15.0.tgz", - "integrity": "sha512-HBck3wcEeIOa7IQMsUkUKbm9cAU7bjoklIyq2zFGn90k7DcDa++oXK9Z2pmcd4TPoBYiyVuuXucaCcjmLX8V/Q==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/combobox/-/combobox-1.39.1.tgz", + "integrity": "sha512-fmStpG+k4xrxCzqUX0ssnOMeoSietWm5ir3qmEZcagzNqNycAXMvOELAIeyXi87Kut6aDGhxLOV7o395HVXl/w==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/aria-hidden": "1.15.0", - "@zag-js/collection": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/collection": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dismissable": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-visible": "1.39.1", + "@zag-js/live-region": "1.39.1", + "@zag-js/popper": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/core": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.15.0.tgz", - "integrity": "sha512-P/8F3IXabMhpFnc6hC7GDg3rvUnvY27cuZU04hxjUqTH6+SfORIA/Uvqd4ekhC+dIprL9jicnFrmGgcyelyxfQ==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/core/-/core-1.39.1.tgz", + "integrity": "sha512-Yp0r49QLYXe2j7fgyAiilH4umXFydCnr5hcRDwJU+sxvUAlq00JQIJIEK2pT6k8cJiNNsFEV5WkOX7jsqpAX2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/date-picker": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/date-picker/-/date-picker-1.39.1.tgz", + "integrity": "sha512-t9q1H0aZQJkbzKTR2Bn5vMwaoFoirxekiSxw8ju0F0vr4Kg4BJ9yueOQm5I2wALKnJbZu4Ua5MgzlrDF3CQt3A==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/date-utils": "1.39.1", + "@zag-js/dismissable": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/live-region": "1.39.1", + "@zag-js/popper": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + }, + "peerDependencies": { + "@internationalized/date": ">=3.0.0" + } + }, + "node_modules/@zag-js/date-utils": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/date-utils/-/date-utils-1.39.1.tgz", + "integrity": "sha512-i4SvBhru2Yz/zsHT0XvyFhf4a+pAKYkWXeVfU0RvF2S6mPTfgaMFF9ZNPq5Sy8K31EtAa6AVXcybYaYnibn1FA==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@internationalized/date": ">=3.0.0" } }, "node_modules/@zag-js/dialog": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.15.0.tgz", - "integrity": "sha512-Vlt5vySs4u8c8xBEh2JMUvRfPc+aaVEIIUtFVxpc2ORWhBXs9glijyp1yf3rNHJhjj8gqqhF5sEvs3yUTTAk+Q==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/dialog/-/dialog-1.39.1.tgz", + "integrity": "sha512-q+HTmfuRDRZthln9mb7i52wdltQOZlw3+nw3a2uygEe9xuEtHBwUz31XJzkn2UWQqhAt7cC39OwykhNLKrfkqA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/aria-hidden": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-trap": "1.15.0", - "@zag-js/remove-scroll": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/aria-hidden": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dismissable": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-trap": "1.39.1", + "@zag-js/remove-scroll": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/dismissable": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.15.0.tgz", - "integrity": "sha512-yv575KWy8gA1p4aajOiY5l/nBQ3Xw+Mrjpungp1+wiGd/98eNAIKJ6/adldfbE1Ygd/Q4Dx2VQ7D1AmiTdwUSw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/dismissable/-/dismissable-1.39.1.tgz", + "integrity": "sha512-7/soy93Ersd5qedhSL/+CDcZ9gNTQV0ooDcqKtM8b4IxwD4rgWwGsewJY+tbKmOqaZobwa0YcWV2+YGgI23ESw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0", - "@zag-js/interact-outside": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/dom-query": "1.39.1", + "@zag-js/interact-outside": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/dom-query": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.15.0.tgz", - "integrity": "sha512-z8H/j/Zs0eZEsGpbonScmlKSv0jEXKiAwUCrvQ9Mt6Gz9n0CQRM3MkFclSsM8aeiSv6qKLlhPfkzjl18OLkbgA==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/dom-query/-/dom-query-1.39.1.tgz", + "integrity": "sha512-k01aXeUWLyJfB61CODaXj4PLhYmVpnVMFrC+3nk/XCn1MW7my8L/8KVg0m4W8n+X9MhpaLWsZDmK/dwED/3qSw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/types": "1.15.0" + "@zag-js/types": "1.39.1" } }, "node_modules/@zag-js/file-upload": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.15.0.tgz", - "integrity": "sha512-2hAlQr9qdT8EH4XnmkNkEIDCCsmp2SMoMAjq6nJKYO8UJNQGRanU2B5S8jV3quJBz0vIY43SwyvqiZ3+1VrJSg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/file-upload/-/file-upload-1.39.1.tgz", + "integrity": "sha512-cErPOnPwPyneUXpelsfm75DKn0/4SI8aqQnlbrqo522PEqAQyDfDdBsqebGgKWG3F0A++kKFp9LO9A5zCrw5gA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/file-utils": "1.15.0", - "@zag-js/i18n-utils": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/file-utils": "1.39.1", + "@zag-js/i18n-utils": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/file-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.15.0.tgz", - "integrity": "sha512-tahJt3JmrXaOtGiknH5PxIiOyyNvroMfjiBqOqnNksIPzDoWmVNxHOEme/ts7dJlkRD8U2qm2NFC2VS0bKerzg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/file-utils/-/file-utils-1.39.1.tgz", + "integrity": "sha512-ll/W5o74SMmoAS+l7PkmmGjPj4PLCSG/cwQh1Y/+LpaSev0YiR3Nk2OzRIIPtm3NivYVxKGawaCOf1RvT/82LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/i18n-utils": "1.39.1" + } + }, + "node_modules/@zag-js/floating-panel": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/floating-panel/-/floating-panel-1.39.1.tgz", + "integrity": "sha512-IfPbf3pwJGqBWHec/rPzpdPjfMCLed59LlEophvRy49FEdksv8eN6nr9DXl2wWZEoQhH99scXfLMbtEZsPsFWg==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/i18n-utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/popper": "1.39.1", + "@zag-js/rect-utils": "1.39.1", + "@zag-js/store": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/focus-trap": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.15.0.tgz", - "integrity": "sha512-N8m/JpNe1gHUPJlr0hyGUdHg6pAuyJKkBaX0s38cyVntlo2CJhyAWZGuUdocpT2Q3HNPql666FNnH986rYPDKQ==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/focus-trap/-/focus-trap-1.39.1.tgz", + "integrity": "sha512-2ZzVefHMotvtxUo/gP4R45Szw/EPaPkTKEHaug6/il62SPDbkFODF+5r1zXyLbLuwCHq0apvQasg/ONLihwlXw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.39.1" } }, "node_modules/@zag-js/focus-visible": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.15.0.tgz", - "integrity": "sha512-TPXBf47tj6L0hhZNl9AWhuLoVzfPaNPM+/Gw8t9l9Whvy6v9rk/rqUCidY5LsrQuPiKTi7s5WI5J+Wod8ib3gw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/focus-visible/-/focus-visible-1.39.1.tgz", + "integrity": "sha512-iEuTOYHE8HRn/7ULC9c9BTTWo0C0MJRCbYVxbh/d7v8qAuq4CS76pdfceNo3KeWbb968T+yiG6q0AjiHsr8IOw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.39.1" } }, "node_modules/@zag-js/i18n-utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.15.0.tgz", - "integrity": "sha512-anxSbT8kLbJaFJFSb0Ork2j/Lp+XVfMNCIgiBR2BuqUlfX72k23TIJvRxAfwNIkUfs0L8ikaSgLss9OwS4mAnw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/i18n-utils/-/i18n-utils-1.39.1.tgz", + "integrity": "sha512-TKRLQQlHgJ4cxsHo3tZPtbFjGu9m1UPtfezRGFKq7A8czhdqRhaCpaWF849cd6dI7x6rWvvTan858gOFpyANnQ==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.39.1" } }, "node_modules/@zag-js/interact-outside": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.15.0.tgz", - "integrity": "sha512-OwBf/iesQGU9Oq3xe/tcK7gu7xipiGWsmwl2CcScr0fTp3BIMbQywHS928IgPk1DxA8KTHodY8wBjoY1dskfRA==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/interact-outside/-/interact-outside-1.39.1.tgz", + "integrity": "sha512-LnSbA+txMsFmzNPn84QKH01x2yJv4At/eKHn6rT2PyxXkJQIh8PvCTS3zVz4Syw11cmhcXt2eRwhzx8yImV92w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/listbox": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/listbox/-/listbox-1.39.1.tgz", + "integrity": "sha512-Mz0UpdXobdTQTyjM+Avgi7pDVB2dKyaUHqw3TloeleQL3VwTqClclkwHXtLYYE+oXa0zOet37wI9mzfaYx9iZQ==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/collection": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-visible": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/live-region": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.15.0.tgz", - "integrity": "sha512-Xy1PqLZD9AKzKuTKCMo9miL1Xizk/N8qFvj64iybBKUYnKr89/af3w7hRFqd2BDX+q3zrNxPp9rZ6L7MlOc7kA==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/live-region/-/live-region-1.39.1.tgz", + "integrity": "sha512-E7YNd0QGzJ2n1ZhnI2smv+klwifsNRf9QaDCx7quVJCVYywpupsBK4R25KN75S1z8XaK+jAy6HYKj8DIhYjYeg==", "dev": true, "license": "MIT" }, + "node_modules/@zag-js/menu": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/menu/-/menu-1.39.1.tgz", + "integrity": "sha512-bRDGLGkiGhzNtORBXkbBQV/xp2zEkwpYIepfWCaUoFwKUmx7GGnShTBFxJyq0u2D4IkS9GOwcqm20EhMv6V+TA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dismissable": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-visible": "1.39.1", + "@zag-js/popper": "1.39.1", + "@zag-js/rect-utils": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, "node_modules/@zag-js/pagination": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.15.0.tgz", - "integrity": "sha512-Z62Q41fQPWqk59QyJk+9J0Ad3H9DCqZ0zZutI6iH8DdzT0A0xxmT6zhup6DM/8C8h0OLlaHFTWQnj0RdRNrnXg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/pagination/-/pagination-1.39.1.tgz", + "integrity": "sha512-3Q1B9/g3ajhvXjuGffJ7otyXcXK5+uhdbE5A9CZa4bsW3pf25L9Cp+ZAjdXQMDc8T4jhZJAKFmDJfQgtr1oEIw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/popover": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.15.0.tgz", - "integrity": "sha512-cdzEed3zcGbjSgPQnQnrsuXo2hVVslmSNwQbU5dHcNzG1uxxmtPCIMVeBUmGyJbAFF5XQpKCq/7mIr26dT73vw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/popover/-/popover-1.39.1.tgz", + "integrity": "sha512-aO3ExO/O7Sa3ovdozFI6SujhNOpYdCca4bImnAiovDL8DY8zN3UNQebu35IQvw9/aRsx9VKSJL1AqzJJUImFRw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/aria-hidden": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-trap": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/remove-scroll": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/aria-hidden": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dismissable": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-trap": "1.39.1", + "@zag-js/popper": "1.39.1", + "@zag-js/remove-scroll": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/popper": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.15.0.tgz", - "integrity": "sha512-Ra/0Ko423KN+8D4+mIFFkeTn9uaHfpxn6UUNIWwZKoiJQvED8DH4dPbLbmvGEoKp6qmisnRHAzi71NLgEhk0Mw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/popper/-/popper-1.39.1.tgz", + "integrity": "sha512-h0UMY2dXJNfM3OvMQ9t9LzlmwvpCgjloz2IvU1txY3r32UIy7ve1H70zkKagLtLRxFTuWmhumYUPULPo/6a1DA==", "dev": true, "license": "MIT", "dependencies": { - "@floating-ui/dom": "1.7.1", - "@zag-js/dom-query": "1.15.0", - "@zag-js/utils": "1.15.0" + "@floating-ui/dom": "^1.7.6", + "@zag-js/dom-query": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/progress": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.15.0.tgz", - "integrity": "sha512-/Mz26GR2rOAuoErNOiSGRpvwckTmbCD5nWGDE/aYlVRID13HcsmN15Zk2Jfa4LadqK88aIN8Iy0Sk4elG0+Efw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/progress/-/progress-1.39.1.tgz", + "integrity": "sha512-1IHyOw8DqPs3YH149Oj7W9a5oEfY5pc9GAVOPGbzYxVK/W8d/NIjVxa565I3J5cDJ0s6z3FrMSXMWUwr1ML4tw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/radio-group": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.15.0.tgz", - "integrity": "sha512-+KTebHUtMsE/YDyGE8wF5VnWfZQp+f2WoAwwzBjfhPpRxXbOUMDo0pZEEr3yxkSvQ9hgCcBhMKH8pEk0SPxvjQ==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/radio-group/-/radio-group-1.39.1.tgz", + "integrity": "sha512-+sC9xcAyY/GbY+8HpKlbPgSyOxBLUSB18s6fe6K1wdmyom4PM0nmhLouuxisbFZYHOyfQwAOMo+ainRENB2hzQ==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-visible": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/rating-group": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.15.0.tgz", - "integrity": "sha512-omGKN97FhplFwBX9J/Mj7BCZuwFXSXssSVTKU7Yp2d1Cmxhez4+Ju7KdSRNnIoWB4OxFCxwZyaAPTcg3E0Pjrg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/rating-group/-/rating-group-1.39.1.tgz", + "integrity": "sha512-IfdxWmM+3zpztx/HcE3bWob72sZNb1+BzK4tSySLVyjeqs8OzLDzrCbKqt10DmibnNOvpbjbq4eX4P5hV9YN7Q==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, + "node_modules/@zag-js/rect-utils": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/rect-utils/-/rect-utils-1.39.1.tgz", + "integrity": "sha512-5gJ0PzeUme76xTWG+4XythWgmGgDKV4XAxEUaB3KKDtXgjDHwtu7PwKLIzFtlaaSf/U23PY+RNVBVCYg1GmZog==", + "dev": true, + "license": "MIT" + }, "node_modules/@zag-js/remove-scroll": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.15.0.tgz", - "integrity": "sha512-vdWSAdgY8wJ7s4YeaKwTMwmZiRMBxCehmdktSxBWvwtAjU1cM3UWvjmZ9E6INJrQXxH9vDpe/rpFSyv1guIQIw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/remove-scroll/-/remove-scroll-1.39.1.tgz", + "integrity": "sha512-uZfPR3Gl9sQFo+tJ7kbuwsBhw+RIZwWFnMDgrz5LIwSNGN6hsyC4HGOxe29clkWQ2X2AjqqmEMETwgX7Jg+wxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/dom-query": "1.39.1" + } + }, + "node_modules/@zag-js/scroll-snap": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/scroll-snap/-/scroll-snap-1.39.1.tgz", + "integrity": "sha512-AzCc8MAAVqkiK5Y0cJZ24OIBZDQrUmEexACMuR6M5yZmlcEbS0EA/d6Wq+LSR1JMVTD4B+UwcMj1D3vJQ90ZTw==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/dom-query": "1.15.0" + "@zag-js/dom-query": "1.39.1" } }, "node_modules/@zag-js/slider": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.15.0.tgz", - "integrity": "sha512-NYIsn3GKXIoPmvkDXsQmw9wdYg3QHbYHXnZ8Ewl2fVubN7S5mDlHSZs2iDVsBvX+a4RChWFRO6JHX8E1+BncOg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/slider/-/slider-1.39.1.tgz", + "integrity": "sha512-OEA9R7Ly5cw+6ANofnMpuHH3rAo8gZEnxy7iEwePu11pq2RCnt8DSj2V+uqU+dTq15Uup1LSzRgJfTnAC4Z85A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/steps": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/steps/-/steps-1.39.1.tgz", + "integrity": "sha512-DC6swMpwITTB0DyCSxlpWyPNSUN9ul9jz4N6aAyQ0L1IK/noF/YYTZRAcXNSRzN4iutO/2mFGGbwGq/oVf+gPA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/store": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.15.0.tgz", - "integrity": "sha512-ecqjcy3b1GsULpsT8RVJV9KDaikajRN0XRg48HMvaGkaPIvxI6esyrE6RKnShuqr2eVXIPghgBnCnrJUev4UlA==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/store/-/store-1.39.1.tgz", + "integrity": "sha512-zFpwP4lhiBVD9987rwAfZNVa2/f/xx4mhbCE1EEw31zxLAozY2jONeJ3UzPP05VbzKlRHBcvkaXAJQQGegTwFA==", "dev": true, "license": "MIT", "dependencies": { @@ -2745,112 +3077,140 @@ } }, "node_modules/@zag-js/svelte": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/svelte/-/svelte-1.15.0.tgz", - "integrity": "sha512-g+tdIYdM6VXdq/oQpNCPnOw4oBwpYKKlUorwkK5PPB9DXI+hCvem9mtBp/o+H6xkvvse61JaFZl03ietBaIi3A==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/svelte/-/svelte-1.39.1.tgz", + "integrity": "sha512-ZOyZjyvjePZdrkNTy5fa92ijeeID9e+3LRGziKGIII3JSEvwfkG/Buf8W84N8VHFxi0G0GcKmgVCDgKHyGQYoQ==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/core": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/core": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" }, "peerDependencies": { - "svelte": "^5.0.0-next.1" + "svelte": ">=5" } }, "node_modules/@zag-js/switch": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.15.0.tgz", - "integrity": "sha512-2CaAUTi7jM4lJjCYoSE1HWlFPCifI5GR+hufWOCYKpanf8VA/LM+t/a2Aq5QoBsWdcQv3B9mHxF/aVTDbnCKPQ==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/switch/-/switch-1.39.1.tgz", + "integrity": "sha512-ikeQ42c0vyyPLeyW9U0dvcqTV1Ekpx5jZ050R905HGJ2GeWE0uBGuHbMpTG5U6Pwb0a+TMzqAr+jMsquVTCwzg==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-visible": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/tabs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.15.0.tgz", - "integrity": "sha512-voHWpibC1TKLmbAJfixOesxrCio7wK+gdLRvh7Xh5u+3VSsT2fP2wEw3ySkJbpw3MpEE7R2OWkInbCV/SwPcsA==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/tabs/-/tabs-1.39.1.tgz", + "integrity": "sha512-P2RThO1gX9SFsNqrAGPsXJxrjn5YqP6MFs9mdExU+tzzZyVjJQADkAmh98C0eEaCb6HKLpJZ/17hrnLDhm1Tig==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/tags-input": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.15.0.tgz", - "integrity": "sha512-CB60z+/I/Nso1gwatTO1qrk4XITxDd4qtRD+l6fuuKyOkZGgKm0AP0W+/6qUuOvtWIuY6fas3yZHFmF2eEZ9vQ==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/tags-input/-/tags-input-1.39.1.tgz", + "integrity": "sha512-tc0+bd9FiUJwa+wY2hSVVGHLIBC3C3rOZX/4zjchRMs1xgl92c1/tYbytXny7ABB8ZMHveG7MtgDppVF4VkwBg==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/auto-resize": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/interact-outside": "1.15.0", - "@zag-js/live-region": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/auto-resize": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/interact-outside": "1.39.1", + "@zag-js/live-region": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/toast": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.15.0.tgz", - "integrity": "sha512-0RupMCXyGr7/La4Zlei7VqBF0VPNJelGd7zimLboe+IKZyy4Ypi/N2IX14rl8JZQDsDEgkLUl33xrSk/9RW2nQ==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/toast/-/toast-1.39.1.tgz", + "integrity": "sha512-K7ndEfBTKDds10iQKCQUmin74s6V4BEIypAIyQxs18gQB9TCn5+wff886JAzecIKPY97PDQHDKjYR71yzRC7/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dismissable": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/toggle-group": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/toggle-group/-/toggle-group-1.39.1.tgz", + "integrity": "sha512-KS4Bo17foMKXVBhQjocRf4GQxMV4pMXclTo14IWjldaHs2HIrNJ0Ar0Ri+vo47BBKBNsXs4HuNvfbMdQj94wEA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dismissable": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/tooltip": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.15.0.tgz", - "integrity": "sha512-sOpVECyfdS4RZBx46mSV+RPc9C5k9JvYQYUfoOVWh0E5RLSEz5bQm5xxctKOHfCOv+vJNTfG5gP596B1r2+Fkw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/tooltip/-/tooltip-1.39.1.tgz", + "integrity": "sha512-IsxFj7l8kPciwIyYJWlmQ7mhXocbjXxLj3m9z099slYOF7lApA33/ndY32w9ptrI4/nUh2nldzw6eRfSpVnuOA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@zag-js/anatomy": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/focus-visible": "1.39.1", + "@zag-js/popper": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" + } + }, + "node_modules/@zag-js/tree-view": { + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/tree-view/-/tree-view-1.39.1.tgz", + "integrity": "sha512-sm6qUZjO0OaqBqO5s55KU+l5p1wXfUVScoen7BYVoFBuROH7qAZJi8YMclGvnnlyV506i8Hk0qqWnLg0F38jCA==", "dev": true, "license": "MIT", "dependencies": { - "@zag-js/anatomy": "1.15.0", - "@zag-js/core": "1.15.0", - "@zag-js/dom-query": "1.15.0", - "@zag-js/focus-visible": "1.15.0", - "@zag-js/popper": "1.15.0", - "@zag-js/store": "1.15.0", - "@zag-js/types": "1.15.0", - "@zag-js/utils": "1.15.0" + "@zag-js/anatomy": "1.39.1", + "@zag-js/collection": "1.39.1", + "@zag-js/core": "1.39.1", + "@zag-js/dom-query": "1.39.1", + "@zag-js/types": "1.39.1", + "@zag-js/utils": "1.39.1" } }, "node_modules/@zag-js/types": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.15.0.tgz", - "integrity": "sha512-lV2ov2M07BlmjDUCSwBeHxPApHI3oAiLytG94AqcYvQ0BtsCRo5T60yRQ0syFc6fHf0e9+kwt89uoIgfGFYfmw==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/types/-/types-1.39.1.tgz", + "integrity": "sha512-w3vVpgxmdJvMDvv19DXTtFI6kJL6TXw//U0Z1BAc3rnDA9orcB9Ryw4uMNvIzFA607CgssyJcWDaQ/M3yAcbJw==", "dev": true, "license": "MIT", "dependencies": { - "csstype": "3.1.3" + "csstype": "3.2.3" } }, "node_modules/@zag-js/utils": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.15.0.tgz", - "integrity": "sha512-XctFny5H8C00BsougV40Yp0qVEj9M2d/NRme7B33mon9wG+3hscZwP6miJmF6BYI5Pgu6e2P0Sv45FddQU1Tkg==", + "version": "1.39.1", + "resolved": "https://registry.npmjs.org/@zag-js/utils/-/utils-1.39.1.tgz", + "integrity": "sha512-9k741cH7L655Ua3tedTkuMblcXVXVgCLTB9svp9oTjA7oatpOpYF4z43kgAQVjyThNXMJ7AvtO4C80ajQLTScg==", "dev": true, "license": "MIT" }, @@ -2940,6 +3300,7 @@ "version": "5.3.2", "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "dev": true, "license": "Apache-2.0", "engines": { "node": ">= 0.4" @@ -3229,9 +3590,9 @@ } }, "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", "dev": true, "license": "MIT" }, @@ -3337,10 +3698,9 @@ } }, "node_modules/devalue": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.1.1.tgz", - "integrity": "sha512-maua5KUiapvEwiEAe+XnlZ3Rh0GD+qI1J/nb9vrJc3muPXvcF/8gXYTWF76+5DAqHyDUtOIImEuo0YKE9mshVw==", - "dev": true, + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.7.1.tgz", + "integrity": "sha512-MUbZ586EgQqdRnC4yDrlod3BEdyvE4TapGYHMW2CiaW+KkkFmWEFqBUaLltEZCGi0iFXCEjRF0OjF0DV2QHjOA==", "license": "MIT" }, "node_modules/dom-accessibility-api": { @@ -3385,9 +3745,9 @@ "license": "MIT" }, "node_modules/esbuild": { - "version": "0.25.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.5.tgz", - "integrity": "sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==", + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -3398,31 +3758,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.5", - "@esbuild/android-arm": "0.25.5", - "@esbuild/android-arm64": "0.25.5", - "@esbuild/android-x64": "0.25.5", - "@esbuild/darwin-arm64": "0.25.5", - "@esbuild/darwin-x64": "0.25.5", - "@esbuild/freebsd-arm64": "0.25.5", - "@esbuild/freebsd-x64": "0.25.5", - "@esbuild/linux-arm": "0.25.5", - "@esbuild/linux-arm64": "0.25.5", - "@esbuild/linux-ia32": "0.25.5", - "@esbuild/linux-loong64": "0.25.5", - "@esbuild/linux-mips64el": "0.25.5", - "@esbuild/linux-ppc64": "0.25.5", - "@esbuild/linux-riscv64": "0.25.5", - "@esbuild/linux-s390x": "0.25.5", - "@esbuild/linux-x64": "0.25.5", - "@esbuild/netbsd-arm64": "0.25.5", - "@esbuild/netbsd-x64": "0.25.5", - "@esbuild/openbsd-arm64": "0.25.5", - "@esbuild/openbsd-x64": "0.25.5", - "@esbuild/sunos-x64": "0.25.5", - "@esbuild/win32-arm64": "0.25.5", - "@esbuild/win32-ia32": "0.25.5", - "@esbuild/win32-x64": "0.25.5" + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" } }, "node_modules/esbuild-wasm": { @@ -3661,12 +4022,20 @@ } }, "node_modules/esrap": { - "version": "1.4.9", - "resolved": "https://registry.npmjs.org/esrap/-/esrap-1.4.9.tgz", - "integrity": "sha512-3OMlcd0a03UGuZpPeUC1HxR3nA23l+HEyCiZw3b3FumJIN9KphoGzDJKMXI1S72jVS1dsenDyQC0kJlO1U9E1g==", + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.5.tgz", + "integrity": "sha512-/yLB1538mag+dn0wsePTe8C0rDIjUOaJpMs2McodSzmM2msWcZsBSdRtg6HOBt0A/r82BN+Md3pgwSc/uWt2Ig==", "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "peerDependencies": { + "@typescript-eslint/types": "^8.2.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/types": { + "optional": true + } } }, "node_modules/esrecurse": { @@ -3784,11 +4153,14 @@ } }, "node_modules/fdir": { - "version": "6.4.5", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.5.tgz", - "integrity": "sha512-4BG7puHpVsIYxZUbiUE3RqGloLaSSwzYie5jvasC4LWuBWzZawynvYouhjbQKw2JuIGYdm0DzIxl8iVidKlUEw==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -4599,12 +4971,12 @@ } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" + "@jridgewell/sourcemap-codec": "^1.5.5" } }, "node_modules/merge2": { @@ -4776,6 +5148,17 @@ "dev": true, "license": "MIT" }, + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", + "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4897,9 +5280,9 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", + "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", "dev": true, "license": "MIT", "engines": { @@ -4910,9 +5293,9 @@ } }, "node_modules/postcss": { - "version": "8.5.4", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.4.tgz", - "integrity": "sha512-QSa9EBe+uwlGTFmHsPKokv3B/oEMQZxfqW0QqNCyhpa6mB1afzulwn8hihglqAb2pOw+BJgNlmXQ8la2VeHB7w==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.10.tgz", + "integrity": "sha512-pMMHxBOZKFU6HgAZ4eyGnwXF/EvPGGqUr0MnZ5+99485wwW41kW91A4LOGxSHhgugZmSChL5AlElNdwlNgcnLQ==", "dev": true, "funding": [ { @@ -5301,13 +5684,13 @@ } }, "node_modules/rollup": { - "version": "4.42.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.42.0.tgz", - "integrity": "sha512-LW+Vse3BJPyGJGAJt1j8pWDKPd73QM8cRXYK1IxOBgL2AGLu7Xd2YOW0M2sLUBCkF5MshXXtMApyEAEzMVMsnw==", + "version": "4.60.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.60.2.tgz", + "integrity": "sha512-J9qZyW++QK/09NyN/zeO0dG/1GdGfyp9lV8ajHnRVLfo/uFsbji5mHnDgn/qYdUHyCkM2N+8VyspgZclfAh0eQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.7" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -5317,36 +5700,34 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.42.0", - "@rollup/rollup-android-arm64": "4.42.0", - "@rollup/rollup-darwin-arm64": "4.42.0", - "@rollup/rollup-darwin-x64": "4.42.0", - "@rollup/rollup-freebsd-arm64": "4.42.0", - "@rollup/rollup-freebsd-x64": "4.42.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.42.0", - "@rollup/rollup-linux-arm-musleabihf": "4.42.0", - "@rollup/rollup-linux-arm64-gnu": "4.42.0", - "@rollup/rollup-linux-arm64-musl": "4.42.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.42.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-gnu": "4.42.0", - "@rollup/rollup-linux-riscv64-musl": "4.42.0", - "@rollup/rollup-linux-s390x-gnu": "4.42.0", - "@rollup/rollup-linux-x64-gnu": "4.42.0", - "@rollup/rollup-linux-x64-musl": "4.42.0", - "@rollup/rollup-win32-arm64-msvc": "4.42.0", - "@rollup/rollup-win32-ia32-msvc": "4.42.0", - "@rollup/rollup-win32-x64-msvc": "4.42.0", + "@rollup/rollup-android-arm-eabi": "4.60.2", + "@rollup/rollup-android-arm64": "4.60.2", + "@rollup/rollup-darwin-arm64": "4.60.2", + "@rollup/rollup-darwin-x64": "4.60.2", + "@rollup/rollup-freebsd-arm64": "4.60.2", + "@rollup/rollup-freebsd-x64": "4.60.2", + "@rollup/rollup-linux-arm-gnueabihf": "4.60.2", + "@rollup/rollup-linux-arm-musleabihf": "4.60.2", + "@rollup/rollup-linux-arm64-gnu": "4.60.2", + "@rollup/rollup-linux-arm64-musl": "4.60.2", + "@rollup/rollup-linux-loong64-gnu": "4.60.2", + "@rollup/rollup-linux-loong64-musl": "4.60.2", + "@rollup/rollup-linux-ppc64-gnu": "4.60.2", + "@rollup/rollup-linux-ppc64-musl": "4.60.2", + "@rollup/rollup-linux-riscv64-gnu": "4.60.2", + "@rollup/rollup-linux-riscv64-musl": "4.60.2", + "@rollup/rollup-linux-s390x-gnu": "4.60.2", + "@rollup/rollup-linux-x64-gnu": "4.60.2", + "@rollup/rollup-linux-x64-musl": "4.60.2", + "@rollup/rollup-openbsd-x64": "4.60.2", + "@rollup/rollup-openharmony-arm64": "4.60.2", + "@rollup/rollup-win32-arm64-msvc": "4.60.2", + "@rollup/rollup-win32-ia32-msvc": "4.60.2", + "@rollup/rollup-win32-x64-gnu": "4.60.2", + "@rollup/rollup-win32-x64-msvc": "4.60.2", "fsevents": "~2.3.2" } }, - "node_modules/rollup/node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/rrweb-cssom": { "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", @@ -5425,9 +5806,9 @@ } }, "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-3.1.0.tgz", + "integrity": "sha512-kjnC1DXBHcxaOaOXBHBeRtltsDG2nUiUni+jP92M9gYdW12rsmx92UsfpH7o5tDRs7I1ZZPSQJQGv3UaRfCiuw==", "dev": true, "license": "MIT" }, @@ -5552,21 +5933,23 @@ } }, "node_modules/svelte": { - "version": "5.33.18", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.33.18.tgz", - "integrity": "sha512-GVAhi8vi8pGne/wlEdnfWIJvSR9eKvEknxjfL5Sr8gQALiyk8Ey+H0lhUYLpjW+MrqgH9h4dgh2NF6/BTFprRg==", + "version": "5.53.5", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.53.5.tgz", + "integrity": "sha512-YkqERnF05g8KLdDZwZrF8/i1eSbj6Eoat8Jjr2IfruZz9StLuBqo8sfCSzjosNKd+ZrQ8DkKZDjpO5y3ht1Pow==", "license": "MIT", "dependencies": { - "@ampproject/remapping": "^2.3.0", + "@jridgewell/remapping": "^2.3.4", "@jridgewell/sourcemap-codec": "^1.5.0", "@sveltejs/acorn-typescript": "^1.0.5", "@types/estree": "^1.0.5", + "@types/trusted-types": "^2.0.7", "acorn": "^8.12.1", - "aria-query": "^5.3.1", + "aria-query": "5.3.1", "axobject-query": "^4.1.0", "clsx": "^2.1.1", + "devalue": "^5.6.3", "esm-env": "^1.2.1", - "esrap": "^1.4.8", + "esrap": "^2.2.2", "is-reference": "^3.0.3", "locate-character": "^3.0.0", "magic-string": "^0.30.11", @@ -5658,6 +6041,15 @@ "integrity": "sha512-mthHQ2TwiwzTWzbFry3CBnVEfzqPOD9WkVw84OfSYzHRq6N9wgQ+yv37u81uPeuLU/ZOIPqhujpXquB1aol5ZQ==", "license": "MIT" }, + "node_modules/svelte/node_modules/aria-query": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.1.tgz", + "integrity": "sha512-Z/ZeOgVl7bcSYZ/u/rh0fOpvEpq//LZmdbkXyc7syVzjPAhfOa9ebsdTSjEBDU4vs5nC98Kfduj1uFo0qyET3g==", + "license": "Apache-2.0", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/symbol-tree": { "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", @@ -5715,14 +6107,14 @@ "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.14", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz", - "integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==", + "version": "0.2.16", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz", + "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.4" }, "engines": { "node": ">=12.0.0" @@ -5953,9 +6345,9 @@ } }, "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", + "version": "6.4.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.2.tgz", + "integrity": "sha512-2N/55r4JDJ4gdrCvGgINMy+HH3iRpNIz8K6SFwVsA+JbQScLiC+clmAxBgwiSPgcG9U15QmvqCGWzMbqda5zGQ==", "dev": true, "license": "MIT", "dependencies": { @@ -6050,22 +6442,582 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/vitefu": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.0.6.tgz", - "integrity": "sha512-+Rex1GlappUyNN6UfwbVZne/9cYC4+R2XDk9xkNXBKMw6HQagdX9PgZ8V2v1WUSK1wfBLp7qbI1+XSNIlB1xmA==", + "node_modules/vite-node/node_modules/vite": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", "dev": true, "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0" + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" }, - "peerDependenciesMeta": { - "vite": { - "optional": true + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", + "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", + "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", + "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", + "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", + "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", + "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", + "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", + "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", + "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", + "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", + "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", + "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", + "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", + "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", + "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", + "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", + "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", + "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", + "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", + "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", + "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", + "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", + "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", + "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", + "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", + "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.12", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", + "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.12", + "@esbuild/android-arm": "0.25.12", + "@esbuild/android-arm64": "0.25.12", + "@esbuild/android-x64": "0.25.12", + "@esbuild/darwin-arm64": "0.25.12", + "@esbuild/darwin-x64": "0.25.12", + "@esbuild/freebsd-arm64": "0.25.12", + "@esbuild/freebsd-x64": "0.25.12", + "@esbuild/linux-arm": "0.25.12", + "@esbuild/linux-arm64": "0.25.12", + "@esbuild/linux-ia32": "0.25.12", + "@esbuild/linux-loong64": "0.25.12", + "@esbuild/linux-mips64el": "0.25.12", + "@esbuild/linux-ppc64": "0.25.12", + "@esbuild/linux-riscv64": "0.25.12", + "@esbuild/linux-s390x": "0.25.12", + "@esbuild/linux-x64": "0.25.12", + "@esbuild/netbsd-arm64": "0.25.12", + "@esbuild/netbsd-x64": "0.25.12", + "@esbuild/openbsd-arm64": "0.25.12", + "@esbuild/openbsd-x64": "0.25.12", + "@esbuild/openharmony-arm64": "0.25.12", + "@esbuild/sunos-x64": "0.25.12", + "@esbuild/win32-arm64": "0.25.12", + "@esbuild/win32-ia32": "0.25.12", + "@esbuild/win32-x64": "0.25.12" + } + }, + "node_modules/vitefu": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.3.tgz", + "integrity": "sha512-ub4okH7Z5KLjb6hDyjqrGXqWtWvoYdU3IGm/NorpgHncKoLTCfRIbvlhBm7r0YstIaQRYlp4yEbFqDcKSzXSSg==", + "dev": true, + "license": "MIT", + "workspaces": [ + "tests/deps/*", + "tests/projects/*", + "tests/projects/workspace/packages/*" + ], + "peerDependencies": { + "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "vite": { + "optional": true } } }, @@ -6142,6 +7094,108 @@ } } }, + "node_modules/vitest/node_modules/@vitest/mocker": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.2.tgz", + "integrity": "sha512-jKojcaRyIYpDEf+s7/dD3LJt53c0dPfp5zCPXz9H/kcGrSlovU/t1yEaNzM9oFME3dcd4ULwRI/x0Po1Zf+LTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.2", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/vite": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.2.tgz", + "integrity": "sha512-Bby3NOsna2jsjfLVOHKes8sGwgl4TT0E6vvpYgnAYDIF/tie7MRaFthmKuHx1NSXjiTueXH3do80FMQgvEktRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", @@ -6301,21 +7355,6 @@ "node": ">=18" } }, - "node_modules/yaml": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz", - "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==", - "dev": true, - "license": "ISC", - "optional": true, - "peer": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/ui/package.json b/ui/package.json index 301e5dd..29435fa 100644 --- a/ui/package.json +++ b/ui/package.json @@ -19,11 +19,13 @@ "devDependencies": { "@eslint/compat": "^1.2.5", "@eslint/js": "^9.18.0", - "@skeletonlabs/skeleton": "^3.1.2", - "@skeletonlabs/skeleton-svelte": "^1.2.1", + "@inlang/cli": "^3.0.0", + "@inlang/paraglide-js": "2.0.13", + "@skeletonlabs/skeleton": "^4.0.0", + "@skeletonlabs/skeleton-svelte": "^4.0.0", "@sveltejs/adapter-static": "^3.0.8", - "@sveltejs/kit": "^2.16.0", - "@sveltejs/vite-plugin-svelte": "^5.0.0", + "@sveltejs/kit": "^2.58.0", + "@sveltejs/vite-plugin-svelte": "^6.2.4", "@tailwindcss/forms": "^0.5.9", "@tailwindcss/typography": "^0.5.15", "@tailwindcss/vite": "^4.0.0", @@ -37,15 +39,13 @@ "prettier": "^3.4.2", "prettier-plugin-svelte": "^3.3.3", "prettier-plugin-tailwindcss": "^0.6.11", - "svelte": "^5.0.0", + "svelte": "5.53.5", "svelte-check": "^4.0.0", "tailwindcss": "^4.0.0", "typescript": "^5.0.0", "typescript-eslint": "^8.20.0", - "vite": "^6.3.3", - "vitest": "^3.0.0", - "@inlang/paraglide-js": "2.0.13", - "@inlang/cli": "^3.0.0" + "vite": "^6.4.2", + "vitest": "^3.0.0" }, "dependencies": { "@fortawesome/free-brands-svg-icons": "^6.7.2", diff --git a/ui/src/app.css b/ui/src/app.css index ab2978a..010298e 100644 --- a/ui/src/app.css +++ b/ui/src/app.css @@ -1,8 +1,7 @@ @import 'tailwindcss'; @import '@skeletonlabs/skeleton'; -@import '@skeletonlabs/skeleton/optional/presets'; @import '@skeletonlabs/skeleton/themes/hamlindigo'; @import '../src/workshop-walker.css'; @plugin '@tailwindcss/forms'; @plugin '@tailwindcss/typography'; -@source '../node_modules/@skeletonlabs/skeleton-svelte/dist'; +@import '@skeletonlabs/skeleton-svelte'; diff --git a/ui/src/routes/+layout.svelte b/ui/src/routes/+layout.svelte index 847d703..3702978 100644 --- a/ui/src/routes/+layout.svelte +++ b/ui/src/routes/+layout.svelte @@ -20,31 +20,35 @@
- {#snippet lead()} - - - - {/snippet} - Workshop Walker - {#snippet trail()} - {#if logged_in} - - Sign Out + + + + - {:else} - - Sign In Through Steam - - {/if} + + +

Workshop Walker

+
+ + {#if logged_in} + + Sign Out + + {:else} + + Sign In Through Steam + + {/if} - - - - {/snippet} + + + + +
diff --git a/ui/src/routes/+page.svelte b/ui/src/routes/+page.svelte index 0fb800f..f856189 100644 --- a/ui/src/routes/+page.svelte +++ b/ui/src/routes/+page.svelte @@ -1,5 +1,8 @@ @@ -9,14 +12,17 @@ -
- +
+ {#each data.items as app} + + {/each} { + const res = await fetch(`/api/apps`); + const apps = await res.json(); + + return { items: apps }; +}; diff --git a/ui/src/routes/admin/+page.svelte b/ui/src/routes/admin/+page.svelte index 9954e9b..e1fbdf0 100644 --- a/ui/src/routes/admin/+page.svelte +++ b/ui/src/routes/admin/+page.svelte @@ -1,5 +1,6 @@
@@ -80,135 +140,239 @@ {#snippet list()} Properties Users + Apps {/snippet} {#snippet content()} -
- - -
- - - - - - - - - - - - - - {#each properties as property} - {@debug property} - - - - - - - - - {/each} - -
IDClassValueSubmitted ByStatusActions
{property.in}{property.out.class}{property.out.value}{property.source} - {#if property.status === -1} - Denied - {:else if property.status === 0} - Pending - {:else} - Approved - {/if} - - -
+ {@render propertiesPanel()}
- - - - - - - - - - - - {#each users as user} - {@debug user} - - - - - - - - {/each} - -
IDAdminBannedActionsLast Logged In
{user.id} - toggleUserAdmin(user.id, e.target.checked)} - /> - - { - toggleUserBan(user.id, e.target.checked); - }} - /> - - {user.last_logged_in} - - -
+ {@render usersPanel()} +
+ + + + {@render appsPanel()} {/snippet}
+ +{#snippet propertiesPanel()} +
+ + +
+ + + + + + + + + + + + + + {#each properties as property} + + + + + + + + + {/each} + +
Item IDClassValueSubmitted ByStatusActions
{property.in}{property.out.class}{property.out.value}{property.source} + {#if property.status === -1} + Denied + {:else if property.status === 0} + Pending + {:else} + Approved + {/if} + + +
+{/snippet} + +{#snippet usersPanel()} + + + + + + + + + + + + {#each users as user} + + + + + + + + {/each} + +
IDNameAdminBannedLast Logged In
{user.id}{user.name ?? 'unpopulated'} + toggleUserAdmin(user.id, e.target.checked)} + /> + + { + toggleUserBan(user.id, e.target.checked); + }} + /> + + {user.last_logged_in} +
+{/snippet} + +{#snippet appsPanel()} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +{/snippet} diff --git a/ui/src/routes/admin/AdminApps.svelte b/ui/src/routes/admin/AdminApps.svelte new file mode 100644 index 0000000..96111f3 --- /dev/null +++ b/ui/src/routes/admin/AdminApps.svelte @@ -0,0 +1,275 @@ + + +{#if loading} +

Loading…

+{:else if error} +

{error}

+{/if} + +
+ + {@debug apps} + {#each apps as state (state.localKey)} + {@debug state} +
+ + + + {#if !state.collapsed} +
{ + e.preventDefault(); + save(state); + }} + > +
+ + + + + + +