diff --git a/Cargo.lock b/Cargo.lock index a3197e6f..8a95e888 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -75,9 +75,9 @@ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] name = "aws-lc-rs" -version = "1.18.1" +version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +checksum = "faac5829c2b74c28f830747e7818ccfb684261b5f48a1118b1e2a13d36dfab13" dependencies = [ "aws-lc-sys", "zeroize", @@ -85,9 +85,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.45.0" +version = "0.46.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +checksum = "f1622d8446a2d4b2ce0c7eefc73dd43a99779028d5ee5c2dd8073a658ba8a2bc" dependencies = [ "cc", "cmake", @@ -188,9 +188,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.5.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" dependencies = [ "find-msvc-tools", "jobserver", @@ -245,9 +245,9 @@ dependencies = [ [[package]] name = "combine" -version = "4.6.8" +version = "4.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +checksum = "4356eba6976435498d05a311ee9fc486da3bc81c200d3f0d7dd9703b41913f92" dependencies = [ "bytes", "memchr", @@ -423,7 +423,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -445,7 +445,7 @@ checksum = "2ac7135c3ef02b2f7833bbeb1be5ba7f966dcde8a87c6b87f65a778d71a02785" dependencies = [ "darling_core 0.24.1", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -456,9 +456,9 @@ checksum = "5729f5117e208430e437df2f4843f5e5952997175992d1414f94c57d61e270b4" [[package]] name = "deranged" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +checksum = "9e9de72ce2ad1f90dc62fa25f0f430ef85eb4b0d8fa0be4f30373bc40a21d28e" [[package]] name = "derive_more" @@ -484,9 +484,9 @@ dependencies = [ [[package]] name = "diesel" -version = "2.3.13" +version = "2.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b934ddbdcb2abb9f9fc9c30bd47bcc5618b615eea1d334cda5fdf8ff9b072a" +checksum = "ebe9f7eaef33febd60290c5a9f3b0571d03c4c04a24739cd64808ce30e65a5d3" dependencies = [ "chrono", "diesel_derives", @@ -580,7 +580,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -635,9 +635,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] name = "either" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "encoding_rs" @@ -655,9 +655,9 @@ dependencies = [ [[package]] name = "equivalent" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "00d174d5400e5e8fd687ad1049e2f578285fa914201b1af7e8b112a4546bd826" [[package]] name = "errno" @@ -844,9 +844,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.19" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +checksum = "7d29020232d6aa3fb1daca64c1127cf662cf97f254ae16c18c05b8ab635fc118" dependencies = [ "atomic-waker", "bytes", @@ -861,17 +861,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "hashbrown" -version = "0.16.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" -dependencies = [ - "allocator-api2", - "equivalent", - "foldhash", -] - [[package]] name = "hashbrown" version = "0.17.1" @@ -945,9 +934,9 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" +checksum = "2c3e324da4c95177d6291d4c8730197c0d1822f8a9766814a4a44fa5ab797c9c" dependencies = [ "atomic-waker", "bytes", @@ -1146,14 +1135,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", - "hashbrown 0.17.1", + "hashbrown", ] [[package]] name = "indoc" -version = "2.0.7" +version = "2.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +checksum = "a37b2691796cffeb8a8cd305ac66e65841559f147f4e63231d0eafa4db5384d1" dependencies = [ "rustversion", ] @@ -1168,7 +1157,7 @@ dependencies = [ "indoc", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -1283,11 +1272,11 @@ dependencies = [ [[package]] name = "kasuari" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde5057d6143cc94e861d90f591b9303d6716c6b9602309150bd068853c10899" +checksum = "72f14c90e40a6133f4805b83542a7ed7364f56070b447f56e7f4e90297122209" dependencies = [ - "hashbrown 0.16.1", + "hashbrown", "portable-atomic", "thiserror 2.0.21", ] @@ -1306,9 +1295,9 @@ checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "libc" -version = "0.2.189" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] name = "libloading" @@ -1369,9 +1358,9 @@ checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" [[package]] name = "litrs" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" +checksum = "4744e383959f0db86ede514b809b1c53251889093803c05267acc7d4e7030d70" [[package]] name = "lock_api" @@ -1394,7 +1383,7 @@ version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef9ac18847474e638e3702b76c65d4eb93428471a74778ef0f1be711717f89b5" dependencies = [ - "hashbrown 0.17.1", + "hashbrown", ] [[package]] @@ -1405,11 +1394,11 @@ checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" [[package]] name = "mac_address" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b367b50a9be9a5d3b5718c1da74e5d6b9c17647f89752ee2562a470cc3c4eb1a" +checksum = "f3d0581a75c45969c63afd2bb87b1d8b25cfcc556c7a918cf9bb13b0fe8d2381" dependencies = [ - "nix 0.30.1", + "nix 0.31.3", "windows-sys 0.61.2", ] @@ -1446,13 +1435,14 @@ dependencies = [ [[package]] name = "migrations_macros" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36fc5ac76be324cfd2d3f2cf0fdf5d5d3c4f14ed8aaebadb09e304ba42282703" +checksum = "9423d6affd681fb4d25d35885d0d0262c52f8ade16e96f87c064c442e5aa5d47" dependencies = [ "migrations_internals", "proc-macro2", "quote", + "syn 3.0.9", ] [[package]] @@ -1469,9 +1459,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "mio" -version = "1.2.3" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" +checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", "log", @@ -1499,9 +1489,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.30.1" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" dependencies = [ "bitflags 2.13.2", "cfg-if", @@ -1557,9 +1547,9 @@ dependencies = [ [[package]] name = "objc2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" +checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8" dependencies = [ "objc2-encode", ] @@ -1705,19 +1695,21 @@ checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" [[package]] name = "pest" -version = "2.9.2" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45d3aca230fad2e6f6317ca0a72724338c4960cb97168a85cdee66df4a9a21a8" +checksum = "fd47a460a9cbc3b3429c7e22bf0d76653e779319bae45a499ca010c9a990bb23" dependencies = [ "memchr", + "psm", + "stacker", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.9.2" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "284b60557f2c4a2e72ad3f2d34d42685a2fa4a6a61d0d2a10c0ae2a5e916c2cf" +checksum = "203e46697708f7519ab1608393cf89239cafb46b8e6d08a8ffe359359b11ef44" dependencies = [ "pest", "pest_generator", @@ -1725,22 +1717,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.9.2" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d9d1f08a115309ee99268cf85e5228e0e56aa9caf8841ec12866b6be07c3109" +checksum = "e84ae6340a458d3d6cfc73cf328cf3cfe90b2484cd0de25eb66aa954615ed4d5" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.9", ] [[package]] name = "pest_meta" -version = "2.9.2" +version = "2.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed93ba1a9ffcca32130a5188701c81c0c49cf00d4b7c5007d5148951d743adcb" +checksum = "b57f92f32b3dbce6598fd8f5cdf1f06a6072570b8103fa21728fa9036923e710" dependencies = [ "pest", ] @@ -1832,9 +1824,9 @@ dependencies = [ [[package]] name = "powerfmt" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +checksum = "4a6394b9e965e73d0a289ee54f589087e2c676aedf60885baf52c76b771e4958" [[package]] name = "proc-macro2" @@ -1845,6 +1837,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "psm" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "200b9ff220857e53e184257720a14553b2f4aa02577d2ed9842d45d4b9654810" +dependencies = [ + "cc", +] + [[package]] name = "quick-xml" version = "0.41.0" @@ -1998,7 +1999,7 @@ dependencies = [ "bitflags 2.13.2", "compact_str", "critical-section", - "hashbrown 0.17.1", + "hashbrown", "itertools", "kasuari", "lru", @@ -2061,7 +2062,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "66e3d19bcc9130ca376277d93b60767ff121ace3be06f5f95f81dd68956407d1" dependencies = [ "bitflags 2.13.2", - "hashbrown 0.17.1", + "hashbrown", "indoc", "instability", "itertools", @@ -2172,7 +2173,7 @@ dependencies = [ [[package]] name = "rex-app" -version = "0.3.1" +version = "0.3.2" dependencies = [ "anyhow", "chrono", @@ -2187,7 +2188,7 @@ dependencies = [ [[package]] name = "rex-db" -version = "0.3.1" +version = "0.3.2" dependencies = [ "anyhow", "chrono", @@ -2201,14 +2202,14 @@ dependencies = [ [[package]] name = "rex-shared" -version = "0.3.1" +version = "0.3.2" dependencies = [ "chrono", ] [[package]] name = "rex-tui" -version = "0.3.1" +version = "0.3.2" dependencies = [ "anyhow", "atty", @@ -2272,11 +2273,10 @@ dependencies = [ [[package]] name = "rsqlite-vfs" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51c9ae4df8a7fba42103df5c621fa3c37eccf3a3c650879e90fc48b11cc192c" +checksum = "353b74f9810d5b085b6c42c9d86a5f0fdb795553235cdd48753b32e3809d18a7" dependencies = [ - "hashbrown 0.16.1", "thiserror 2.0.21", ] @@ -2310,9 +2310,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.45" +version = "0.23.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +checksum = "48e13bd8c0e9365c43cfa5c9e8f9ad49d3c8444926c9aac819e0e4dc503c8fdf" dependencies = [ "aws-lc-rs", "once_cell", @@ -2324,9 +2324,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +checksum = "4a073f5dc7469f984c52ad2752b63b0807745133b6de880b7b64c1ac4c48aec4" dependencies = [ "openssl-probe", "rustls-pki-types", @@ -2481,14 +2481,14 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] name = "serde_json" -version = "1.0.151" +version = "1.0.154" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" +checksum = "e7e9cc8b1b85264074fbcc02a88680c4096b1e47df8f739dceb03bf482f04bd6" dependencies = [ "itoa", "memchr", @@ -2499,9 +2499,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" dependencies = [ "serde_core", ] @@ -2584,9 +2584,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.16.2" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" [[package]] name = "socket2" @@ -2600,14 +2600,12 @@ dependencies = [ [[package]] name = "sqlite-wasm-rs" -version = "0.5.5" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc3efc0da82635d7e1ced0053bbbfa8c7ab9645d0bf36ceb4f7127bb85315d75" +checksum = "717e14271e332de37b8f7793913d53e2f952b3d21f96efd5880aea42a3c32d18" dependencies = [ "cc", - "js-sys", "rsqlite-vfs", - "wasm-bindgen", ] [[package]] @@ -2616,6 +2614,19 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +[[package]] +name = "stacker" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707f49d46706bacf8a2b00d51dace3f9de527c13eec3778f570c411f89e69967" +dependencies = [ + "cc", + "cfg-if", + "libc", + "psm", + "windows-sys 0.61.2", +] + [[package]] name = "static_assertions" version = "1.1.0" @@ -2679,9 +2690,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.6" +version = "3.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" +checksum = "d78c8dee4c7bf0e14673097256fed6142ce9d3b85a408189d07482442145823b" dependencies = [ "proc-macro2", "quote", @@ -2705,7 +2716,7 @@ checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2842,7 +2853,7 @@ checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] @@ -2901,9 +2912,9 @@ checksum = "fd3ca314f692efd6c868f8408f53fe444634a845f96c028b97d35f6a1f79f0ee" [[package]] name = "tokio" -version = "1.53.1" +version = "1.53.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" +checksum = "ce3335fa71841cda333a58d7615b03901380ecf09d59b3296d21f8bbac0dde4e" dependencies = [ "bytes", "libc", @@ -2925,9 +2936,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.19" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" dependencies = [ "bytes", "futures-core", @@ -2961,9 +2972,9 @@ dependencies = [ [[package]] name = "toml_parser" -version = "1.1.3+spec-1.1.0" +version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" dependencies = [ "winnow 1.0.4", ] @@ -3052,9 +3063,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicode-ident" -version = "1.0.26" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" +checksum = "a2c754d6c33795a1c324727428e5a7dedb5b06195f9890bdbcba760d3e246563" [[package]] name = "unicode-segmentation" @@ -3111,9 +3122,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.26.1" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" +checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ "atomic", "getrandom 0.4.3", @@ -3154,9 +3165,9 @@ dependencies = [ [[package]] name = "want" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +checksum = "ec4cdd0dd910afe868b7ef477227d8d538b46b3075031afee8a9f2acb0a2ed0b" dependencies = [ "try-lock", ] @@ -3219,7 +3230,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "wasm-bindgen-shared", ] @@ -3619,7 +3630,7 @@ checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "synstructure", ] @@ -3640,15 +3651,15 @@ checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", "synstructure", ] [[package]] name = "zeroize" -version = "1.9.0" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" +checksum = "e13084392c5e4bc371903e2935a5eaeed24905a7511356b883835e18a78f6879" [[package]] name = "zerotrie" @@ -3680,7 +3691,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.6", + "syn 3.0.9", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index d8b433ef..1092cd0d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,14 +6,14 @@ resolver = "2" [workspace.dependencies] anyhow = "1.0.104" chrono = "0.4.45" -diesel = { version = "2.3.13", default-features = false, features = [ +diesel = { version = "2.3.14", default-features = false, features = [ "chrono", "returning_clauses_for_sqlite_3_35", "sqlite", ] } -rex-app = "0.3.0" -rex-db = "0.3.0" -rex-shared = "0.3.0" +rex-app = "0.3.2" +rex-db = "0.3.2" +rex-shared = "0.3.2" strum = "0.28.0" strum_macros = "0.28" diff --git a/app/Cargo.toml b/app/Cargo.toml index bac3c68e..7defa162 100644 --- a/app/Cargo.toml +++ b/app/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rex-app" -version = "0.3.1" +version = "0.3.2" edition = "2024" description = "Core functionality for Rex" homepage = "https://github.com/TheRustyPickle/Rex" diff --git a/app/src/views/summary_models.rs b/app/src/views/summary_models.rs index 5f1c3cd2..89d6ff13 100644 --- a/app/src/views/summary_models.rs +++ b/app/src/views/summary_models.rs @@ -15,15 +15,6 @@ pub(crate) struct PeakMonthlyMovement { pub(crate) amount: Cent, } -impl PeakMonthlyMovement { - pub(crate) fn new(date: NaiveDate) -> Self { - Self { - date, - amount: Cent::new(0), - } - } -} - #[derive(Debug)] pub(crate) struct SummaryNet { pub(crate) total_income: Dollar, diff --git a/app/src/views/summary_view.rs b/app/src/views/summary_view.rs index 564b6de2..1f0ffbce 100644 --- a/app/src/views/summary_view.rs +++ b/app/src/views/summary_view.rs @@ -3,7 +3,7 @@ use chrono::{Datelike, NaiveDate}; use rex_db::ConnCache; use rex_db::models::{FetchNature, FullTx, TxType}; use rex_shared::models::{Cent, Dollar}; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use crate::utils::{compare_change, compare_change_opt, get_percentages, month_year_to_unique}; use crate::views::{ @@ -206,23 +206,29 @@ impl SummaryView { let mut income_tags = HashMap::new(); let mut expense_tags = HashMap::new(); + // Only the primary tag. In case in previous month tag x was secondary but in the current + // month x is primary tag, the amount will become inaccurate and secondary tag becomes + // counted. So do not count anything except the primary tag for tx in &self.txs { - for tag in &tx.tags { - match tx.tx_type { - TxType::Income => { - let value = income_tags.entry(tag.name.clone()).or_insert(Cent::new(0)); - *value += tx.amount; - } - TxType::Expense => { - let value = expense_tags.entry(tag.name.clone()).or_insert(Cent::new(0)); - *value += tx.amount; - } - TxType::Transfer - | TxType::Borrow - | TxType::Lend - | TxType::BorrowRepay - | TxType::LendRepay => {} + // First tag is always the primary tag + let Some(tag) = tx.tags.first() else { + continue; + }; + + match tx.tx_type { + TxType::Income => { + let value = income_tags.entry(tag.name.clone()).or_insert(Cent::new(0)); + *value += tx.amount; + } + TxType::Expense => { + let value = expense_tags.entry(tag.name.clone()).or_insert(Cent::new(0)); + *value += tx.amount; } + TxType::Transfer + | TxType::Borrow + | TxType::Lend + | TxType::BorrowRepay + | TxType::LendRepay => {} } } @@ -258,20 +264,13 @@ impl SummaryView { let mut ongoing_month = 0; - let mut ongoing_date = NaiveDate::default(); - - let mut peak_earning = PeakMonthlyMovement::default(); - let mut peak_expense = PeakMonthlyMovement::default(); - - let mut last_peak_earning = PeakMonthlyMovement::default(); - let mut last_peak_expense = PeakMonthlyMovement::default(); + // Income and expense totals per month, keyed by year-month + let mut monthly_totals: BTreeMap = BTreeMap::new(); let mut outstanding_borrows = Cent::new(0); let mut outstanding_lends = Cent::new(0); for tx in &self.txs { - ongoing_date = tx.date.date(); - let time_unique = month_year_to_unique(tx.date.month() as i32, tx.date.year()); if ongoing_month == 0 { @@ -281,18 +280,15 @@ impl SummaryView { if time_unique != ongoing_month { ongoing_month = time_unique; total_month_checked += 1; - - if last_peak_earning.amount > peak_earning.amount { - peak_earning = last_peak_earning; - last_peak_earning = PeakMonthlyMovement::new(tx.date.date()); - } - - if last_peak_expense.amount > peak_expense.amount { - peak_expense = last_peak_expense; - last_peak_expense = PeakMonthlyMovement::new(tx.date.date()); - } } + let month_start = tx.date.date().with_day(1).unwrap(); + let month_total = monthly_totals.entry(time_unique).or_insert(( + month_start, + Cent::new(0), + Cent::new(0), + )); + match tx.tx_type { TxType::Income => { total_income += tx.amount; @@ -308,7 +304,7 @@ impl SummaryView { biggest_earning.method.clone_from(&tx.from_method.name); } - last_peak_earning.amount += tx.amount; + month_total.1 += tx.amount; } TxType::Expense => { total_expense += tx.amount; @@ -324,7 +320,7 @@ impl SummaryView { biggest_expense.method.clone_from(&tx.from_method.name); } - last_peak_expense.amount += tx.amount; + month_total.2 += tx.amount; } TxType::Borrow => { outstanding_borrows += tx.amount; @@ -344,14 +340,23 @@ impl SummaryView { total_month_checked += 1; - if last_peak_earning.amount > peak_earning.amount { - peak_earning = last_peak_earning; - peak_earning.date = ongoing_date; - } + let mut peak_earning = PeakMonthlyMovement::default(); + let mut peak_expense = PeakMonthlyMovement::default(); + + for (date, earning, expense) in monthly_totals.values() { + if *earning > peak_earning.amount { + peak_earning = PeakMonthlyMovement { + date: *date, + amount: *earning, + }; + } - if last_peak_expense.amount > peak_expense.amount { - peak_expense = last_peak_expense; - peak_expense.date = ongoing_date; + if *expense > peak_expense.amount { + peak_expense = PeakMonthlyMovement { + date: *date, + amount: *expense, + }; + } } let (income_percentage, expense_percentage) = @@ -363,7 +368,7 @@ impl SummaryView { Some(total_income.dollar() / f64::from(total_month_checked)) }; - let mut average_expense = if total_income == 0 { + let mut average_expense = if total_expense == 0 { Some(Dollar::new(0.0)) } else { Some(total_expense.dollar() / f64::from(total_month_checked)) diff --git a/app/tests/summary.rs b/app/tests/summary.rs index e58bf1e7..b1a9f623 100644 --- a/app/tests/summary.rs +++ b/app/tests/summary.rs @@ -187,6 +187,44 @@ fn summary_peak_across_months() { fs::remove_file(file_name).unwrap(); } +#[test] +fn summary_peak_does_not_accumulate_across_months() { + let file_name = "test_summary_peak_no_accumulate.sqlite"; + let mut db_conn = create_test_db(file_name); + + // Jan is the true peak. Feb and Mar are each lower, but sum to more than Jan + for (date, income, expense) in [ + ("2024-01-10", "1000.00", "800.00"), + ("2024-02-10", "600.00", "500.00"), + ("2024-03-10", "600.00", "500.00"), + ] { + add_tx(&mut db_conn, date, "I", "Cash", "", income, "Income", "A"); + add_tx(&mut db_conn, date, "E", "Cash", "", expense, "Expense", "B"); + } + + let summary_view = db_conn + .get_summary_with_str("January", "2024", FetchNature::Yearly) + .unwrap(); + let full = summary_view.generate_summary(None, &db_conn); + + let peak = full.peak_array(); + assert_eq!(peak[0][1], "01-2024"); + assert_eq!(peak[0][2], "1000.00"); + assert_eq!(peak[1][1], "01-2024"); + assert_eq!(peak[1][2], "800.00"); + + // Same for all time + let summary_view = db_conn + .get_summary_with_str("January", "2024", FetchNature::All) + .unwrap(); + let peak = summary_view.generate_summary(None, &db_conn).peak_array(); + assert_eq!(peak[0][1], "01-2024"); + assert_eq!(peak[0][2], "1000.00"); + + drop(db_conn); + fs::remove_file(file_name).unwrap(); +} + #[test] fn summary_lend_borrows() { let file_name = "test_summary_lend_borrow.sqlite"; @@ -468,6 +506,62 @@ fn summary_tags_array_with_compare() { fs::remove_file(file_name).unwrap(); } +#[test] +fn summary_tags_compare_counts_primary_tag_only_on_both_sides() { + let file_name = "test_summary_tags_compare_primary.sqlite"; + let mut db_conn = create_test_db(file_name); + + // August: Work primary on one tx, secondary on another + add_tx( + &mut db_conn, + "2024-08-01", + "A", + "Cash", + "", + "500.00", + "Income", + "Work", + ); + add_tx( + &mut db_conn, + "2024-08-02", + "B", + "Cash", + "", + "300.00", + "Income", + "Side, Work", + ); + // September: the same Work income as the primary tag in August + add_tx( + &mut db_conn, + "2024-09-01", + "C", + "Cash", + "", + "500.00", + "Income", + "Work", + ); + + let sep = db_conn + .get_summary_with_str("September", "2024", FetchNature::Monthly) + .unwrap(); + let aug = db_conn + .get_summary_with_str("August", "2024", FetchNature::Monthly) + .unwrap(); + + let tags = sep.tags_array(Some(&aug), &db_conn); + let work_row = tags.iter().find(|r| r[0] == "Work").unwrap(); + + assert_eq!(work_row[1], "500.00"); + // 500 against 500, not against the 800 of every tx that merely mentions Work + assert_eq!(work_row[5], "↑0.00"); + + drop(db_conn); + fs::remove_file(file_name).unwrap(); +} + #[test] fn summary_with_last_summary_mom_comparison() { let file_name = "test_summary_mom.sqlite"; diff --git a/db/Cargo.toml b/db/Cargo.toml index 7ab2c92c..85d5eb07 100644 --- a/db/Cargo.toml +++ b/db/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rex-db" -version = "0.3.1" +version = "0.3.2" edition = "2024" description = "Rex database models using diesel" homepage = "https://github.com/TheRustyPickle/Rex" diff --git a/shared/Cargo.toml b/shared/Cargo.toml index 1655d3af..81d8d9be 100644 --- a/shared/Cargo.toml +++ b/shared/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rex-shared" -version = "0.3.1" +version = "0.3.2" edition = "2024" description = "Shared code for Rex" homepage = "https://github.com/TheRustyPickle/Rex" diff --git a/tui/Cargo.toml b/tui/Cargo.toml index 957acec2..bd1144ec 100644 --- a/tui/Cargo.toml +++ b/tui/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rex-tui" -version = "0.3.1" +version = "0.3.2" edition = "2024" description = "A TUI app for managing Incomes and Expenses." readme = "../README.md" @@ -31,7 +31,7 @@ rex-shared.workspace = true rfd = "0.17.2" semver = "1.0.28" serde = { version = "1.0.229", features = ["derive"] } -serde_json = "1.0.151" +serde_json = "1.0.154" strum.workspace = true strum_macros.workspace = true thousands = "0.2.0"