diff --git a/.prettierignore b/.prettierignore index f81b4f9b16..f4f73090f7 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,5 @@ *.rs +*.lock **/target/ dist/ **/node_modules/ diff --git a/backend/Cargo.lock b/backend/Cargo.lock index fd3d9cda4e..54dd4885db 100644 --- a/backend/Cargo.lock +++ b/backend/Cargo.lock @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "async-io" -version = "2.2.1" +version = "2.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6d3b15875ba253d1110c740755e246537483f152fa334f91abd7fe84c88b3ff" +checksum = "6afaa937395a620e33dc6a742c593c01aced20aa376ffb0f628121198578ccc7" dependencies = [ "async-lock 3.2.0", "cfg-if", @@ -196,7 +196,7 @@ dependencies = [ "futures-lite 2.1.0", "parking", "polling 3.3.1", - "rustix 0.38.26", + "rustix 0.38.28", "slab", "tracing", "windows-sys 0.52.0", @@ -246,7 +246,7 @@ dependencies = [ "cfg-if", "event-listener 3.1.0", "futures-lite 1.13.0", - "rustix 0.38.26", + "rustix 0.38.28", "windows-sys 0.48.0", ] @@ -258,7 +258,7 @@ checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -267,13 +267,13 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e47d90f65a225c4527103a8d747001fc56e375203592b25ad103e1ca13124c5" dependencies = [ - "async-io 2.2.1", + "async-io 2.2.2", "async-lock 2.8.0", "atomic-waker", "cfg-if", "futures-core", "futures-io", - "rustix 0.38.26", + "rustix 0.38.28", "signal-hook-registry", "slab", "windows-sys 0.48.0", @@ -293,7 +293,7 @@ checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -623,6 +623,7 @@ name = "clash-verge" version = "0.1.0" dependencies = [ "anyhow", + "async-trait", "auto-launch", "chrono", "ctrlc", @@ -630,6 +631,7 @@ dependencies = [ "delay_timer", "dirs 5.0.1", "dunce", + "dyn-clone", "glob", "gunzip", "log", @@ -637,15 +639,17 @@ dependencies = [ "nanoid", "once_cell", "open 5.0.1", - "parking_lot", + "parking_lot 0.12.1", "port_scanner", "reqwest", "rquickjs", + "rs-snowflake", "runas", "semver 1.0.20", "serde", "serde_json", "serde_yaml 0.9.27", + "sled", "sysinfo", "sysproxy", "tauri", @@ -732,7 +736,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f76990911f2267d837d9d0ad060aa63aaad170af40904b29461734c339030d4d" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -840,9 +844,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "14c3242926edf34aec4ac3a77108ad4854bffaa2e4ddc1824124ce59231302d5" dependencies = [ "cfg-if", "crossbeam-utils", @@ -850,9 +854,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751" dependencies = [ "cfg-if", "crossbeam-epoch", @@ -861,22 +865,21 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "2d2fe95351b870527a5d09bf563ed3c97c0cffb87cf1c78a591bf48bb218d9aa" dependencies = [ "autocfg", "cfg-if", "crossbeam-utils", "memoffset 0.9.0", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" +checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" dependencies = [ "cfg-if", ] @@ -915,17 +918,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] name = "ctor" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e366bff8cd32dd8754b0991fb66b279dc48f598c3a18914852a6673deef583" +checksum = "30d2b3721e861707777e3195b0158f950ae6dc4a27e4d02ff9f67e3eb3de199e" dependencies = [ "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -959,7 +962,7 @@ dependencies = [ "proc-macro2", "quote", "strsim", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -970,7 +973,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" dependencies = [ "darling_core", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -1177,6 +1180,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56ce8c6da7551ec6c462cbaf3bfbc75131ebbfa1c944aeaa9dab51ca1c5f0c3b" +[[package]] +name = "dyn-clone" +version = "1.0.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "545b22097d44f8a9581187cdf93de7a71e4722bf51200cfaba810865b49a495d" + [[package]] name = "either" version = "1.9.0" @@ -1229,7 +1238,7 @@ checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -1339,7 +1348,7 @@ checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "windows-sys 0.52.0", ] @@ -1386,7 +1395,7 @@ checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -1410,6 +1419,16 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs2" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9564fc758e15025b46aa6643b1b77d047d1a56a1aea6e01002ac0c7026876213" +dependencies = [ + "libc", + "winapi", +] + [[package]] name = "futf" version = "0.1.5" @@ -1504,7 +1523,7 @@ checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -2004,14 +2023,14 @@ checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", - "itoa 1.0.9", + "itoa 1.0.10", ] [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -2057,7 +2076,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.9", + "itoa 1.0.10", "pin-project-lite", "socket2 0.4.10", "tokio", @@ -2300,9 +2319,9 @@ checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "javascriptcore-rs" @@ -2434,9 +2453,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.150" +version = "0.2.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" [[package]] name = "libloading" @@ -2456,7 +2475,7 @@ checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ "bitflags 2.4.1", "libc", - "redox_syscall", + "redox_syscall 0.4.1", ] [[package]] @@ -2526,7 +2545,7 @@ dependencies = [ "libc", "log", "log-mdc", - "parking_lot", + "parking_lot 0.12.1", "serde", "serde-value", "serde_json", @@ -3048,7 +3067,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3059,9 +3078,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "300.1.6+3.1.4" +version = "300.2.1+3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439fac53e092cd7442a3660c85dde4643ab3b5bd39040912388dcdabf6b88085" +checksum = "3fe476c29791a5ca0d1273c697e96085bbabbbea2ef7afd5617e78a4b40332d3" dependencies = [ "cc", ] @@ -3162,6 +3181,17 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" +[[package]] +name = "parking_lot" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" +dependencies = [ + "instant", + "lock_api", + "parking_lot_core 0.8.6", +] + [[package]] name = "parking_lot" version = "0.12.1" @@ -3169,7 +3199,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" dependencies = [ "lock_api", - "parking_lot_core", + "parking_lot_core 0.9.9", +] + +[[package]] +name = "parking_lot_core" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60a2cfe6f0ad2bfc16aefa463b497d5c7a5ecd44a23efa72aa342d90177356dc" +dependencies = [ + "cfg-if", + "instant", + "libc", + "redox_syscall 0.2.16", + "smallvec", + "winapi", ] [[package]] @@ -3180,7 +3224,7 @@ checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.4.1", "smallvec", "windows-targets 0.48.5", ] @@ -3261,7 +3305,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3389,7 +3433,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3436,7 +3480,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -3520,7 +3564,7 @@ dependencies = [ "cfg-if", "concurrent-queue", "pin-project-lite", - "rustix 0.38.26", + "rustix 0.38.28", "tracing", "windows-sys 0.52.0", ] @@ -3738,6 +3782,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -3970,9 +4023,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.26" +version = "0.38.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9470c4bf8246c8daf25f9598dca807fb6510347b1e1cfa55749113850c79d88a" +checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" dependencies = [ "bitflags 2.4.1", "errno", @@ -3983,9 +4036,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.9" +version = "0.21.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629648aced5775d558af50b2b4c7b02983a04b312126d45eeead26e7caa498b9" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", "ring", @@ -4020,9 +4073,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" [[package]] name = "safemem" @@ -4182,7 +4235,7 @@ checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -4191,7 +4244,7 @@ version = "1.0.108" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" dependencies = [ - "itoa 1.0.9", + "itoa 1.0.10", "ryu", "serde", ] @@ -4204,7 +4257,7 @@ checksum = "3081f5ffbb02284dda55132aa26daecedd7372a42417bbbab6f14ab7d6bb9145" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -4223,7 +4276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.9", + "itoa 1.0.10", "ryu", "serde", ] @@ -4254,7 +4307,7 @@ dependencies = [ "darling", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -4276,7 +4329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cc7a1570e38322cfe4154732e5110f887ea57e22b76f4bfd32b5bdd3368666c" dependencies = [ "indexmap 2.1.0", - "itoa 1.0.9", + "itoa 1.0.10", "ryu", "serde", "unsafe-libyaml", @@ -4418,6 +4471,22 @@ dependencies = [ "autocfg", ] +[[package]] +name = "sled" +version = "0.34.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f96b4737c2ce5987354855aed3797279def4ebf734436c6aa4552cf8e169935" +dependencies = [ + "crc32fast", + "crossbeam-epoch", + "crossbeam-utils", + "fs2", + "fxhash", + "libc", + "log", + "parking_lot 0.11.2", +] + [[package]] name = "smallvec" version = "1.11.2" @@ -4524,7 +4593,7 @@ checksum = "f91138e76242f575eb1d3b38b4f1362f10d3a43f47d182a5b359af488a02293b" dependencies = [ "new_debug_unreachable", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "phf_shared 0.10.0", "precomputed-hash", "serde", @@ -4567,9 +4636,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.39" +version = "2.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23e78b90f2fcf45d3e842032ce32e3f2d1545ba6636271dcbf24fa306d87be7a" +checksum = "44c8b28c477cc3bf0e7966561e3460130e1255f7a1cf71931075f1c5e7a7e269" dependencies = [ "proc-macro2", "quote", @@ -4698,7 +4767,7 @@ dependencies = [ "ndk-sys", "objc", "once_cell", - "parking_lot", + "parking_lot 0.12.1", "png", "raw-window-handle", "scopeguard", @@ -4958,8 +5027,8 @@ checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand 2.0.1", - "redox_syscall", - "rustix 0.38.26", + "redox_syscall 0.4.1", + "rustix 0.38.28", "windows-sys 0.48.0", ] @@ -5051,7 +5120,7 @@ checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -5081,7 +5150,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" dependencies = [ "deranged", - "itoa 1.0.9", + "itoa 1.0.10", "powerfmt", "serde", "time-core", @@ -5120,16 +5189,16 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.34.0" +version = "1.35.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c014766411e834f7af5b8f4cf46257aab4036ca95e9d2c144a10f59ad6f5b9" +checksum = "841d45b238a16291a4e1584e61820b8ae57d696cc5015c459c229ccc6990cc1c" dependencies = [ "backtrace", "bytes", "libc", "mio", "num_cpus", - "parking_lot", + "parking_lot 0.12.1", "pin-project-lite", "signal-hook-registry", "socket2 0.5.5", @@ -5145,7 +5214,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -5299,7 +5368,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] @@ -5352,9 +5421,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" @@ -5398,10 +5467,11 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "uds_windows" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce65604324d3cce9b966701489fbd0cf318cb1f7bd9dd07ac9a4ee6fb791930d" +checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" dependencies = [ + "memoffset 0.9.0", "tempfile", "winapi", ] @@ -5644,7 +5714,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", "wasm-bindgen-shared", ] @@ -5678,7 +5748,7 @@ checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -5812,7 +5882,7 @@ dependencies = [ "either", "home", "once_cell", - "rustix 0.38.26", + "rustix 0.38.28", ] [[package]] @@ -6261,9 +6331,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" [[package]] name = "winnow" -version = "0.5.25" +version = "0.5.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e87b8dfbe3baffbe687eef2e164e32286eff31a5ee16463ce03d991643ec94" +checksum = "6c830786f7720c2fd27a1a0e27a709dbd3c4d009b56d098fc742d4f4eab91fe2" dependencies = [ "memchr", ] @@ -6358,11 +6428,13 @@ dependencies = [ [[package]] name = "xattr" -version = "1.0.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4686009f71ff3e5c4dbcf1a282d0a44db3f021ba69350cd42086b3e5f1c6985" +checksum = "a7dae5072fe1f8db8f8d29059189ac175196e410e40ba42d5d4684ae2f750995" dependencies = [ "libc", + "linux-raw-sys 0.4.12", + "rustix 0.38.28", ] [[package]] @@ -6452,22 +6524,22 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.29" +version = "0.7.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d075cf85bbb114e933343e087b92f2146bac0d55b534cbb8188becf0039948e" +checksum = "1c4061bedbb353041c12f413700357bec76df2c7e2ca8e4df8bac24c6bf68e3d" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.29" +version = "0.7.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86cd5ca076997b97ef09d3ad65efe811fa68c9e874cb636ccb211223a813b0c2" +checksum = "b3c129550b3e6de3fd0ba67ba5c81818f9805e58b8d7fee80a3a59d2c9fc601a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.39", + "syn 2.0.41", ] [[package]] diff --git a/backend/tauri/Cargo.toml b/backend/tauri/Cargo.toml index fadef283b3..71415bd4cb 100644 --- a/backend/tauri/Cargo.toml +++ b/backend/tauri/Cargo.toml @@ -56,6 +56,10 @@ zip-extensions = "0.6.2" gunzip = { version = "0.1.0", git = "https://github.com/TechHara/gunzip.git" } tempfile = "3.8.1" glob = "0.3.1" +async-trait = "0.1.74" +dyn-clone = "1.0.16" +rs-snowflake = "0.6" +sled = "0.34.7" [target.'cfg(windows)'.dependencies] runas = "=1.1.0" diff --git a/backend/tauri/src/config/verge.rs b/backend/tauri/src/config/verge.rs index 470b9d6e19..b2aeb4594a 100644 --- a/backend/tauri/src/config/verge.rs +++ b/backend/tauri/src/config/verge.rs @@ -129,6 +129,10 @@ pub struct IVerge { /// proxy 页面布局 列数 pub proxy_layout_column: Option, + /// 日志清理 + /// 分钟数; 0 为不清理 + pub auto_log_clean: Option, + /// window size and position #[deprecated(note = "use `window_size_state` instead")] #[serde(skip_serializing_if = "Option::is_none")] @@ -205,6 +209,7 @@ impl IVerge { enable_builtin_enhanced: Some(true), enable_clash_fields: Some(true), page_transition_animation: Some("slide".into()), + auto_log_clean: Some(60 * 24 * 7), // 7 days 自动清理日记 ..Self::default() } } @@ -255,6 +260,7 @@ impl IVerge { patch!(proxy_layout_column); patch!(enable_clash_fields); + patch!(auto_log_clean); patch!(window_size_position); patch!(window_size_state); } diff --git a/backend/tauri/src/core/mod.rs b/backend/tauri/src/core/mod.rs index e690f28c2e..93fa264810 100644 --- a/backend/tauri/src/core/mod.rs +++ b/backend/tauri/src/core/mod.rs @@ -10,4 +10,6 @@ pub mod tray; pub mod updater; pub mod win_service; pub mod win_uwp; +pub mod tasks; +pub mod storage; pub use self::core::*; diff --git a/backend/tauri/src/core/storage.rs b/backend/tauri/src/core/storage.rs new file mode 100644 index 0000000000..fcc4596025 --- /dev/null +++ b/backend/tauri/src/core/storage.rs @@ -0,0 +1,20 @@ +use crate::utils::dirs; +use once_cell::sync::OnceCell; + +/// storage is a wrapper or called a facade for the sled database + +pub struct Storage { + instance: sled::Db, +} + +impl Storage { + pub fn global() -> &'static Self { + static STORAGE: OnceCell = OnceCell::new(); + + STORAGE.get_or_init(|| { + let path = dirs::storage_path().unwrap(); + let instance = sled::open(path).expect("failed to open storage"); + Storage { instance } + }) + } +} diff --git a/backend/tauri/src/core/tasks/executor.rs b/backend/tauri/src/core/tasks/executor.rs new file mode 100644 index 0000000000..f2fabe512a --- /dev/null +++ b/backend/tauri/src/core/tasks/executor.rs @@ -0,0 +1,95 @@ +use std::fmt::{self, Formatter}; + +use anyhow::Result; +use async_trait::async_trait; +use dyn_clone::{clone_trait_object, DynClone}; + +/// JobExecutor is a trait for job executor +/// It is used to define a sync job +/// +/// For example, you can define a job to print hello. +/// ``` rust +/// use anyhow::Result; +/// #[derive(Clone)] +/// pub struct HelloJob {} +/// impl JobExecutor for HelloJob { +/// fn execute(&self) -> Result<()> { +/// println!("hello"); +/// Ok(()) +/// } +/// } +/// ``` +/// Then you can pass it to the task manager to execute it. +/// +/// +pub trait JobExecutor: DynClone { + fn execute(&self) -> Result<()>; +} + +clone_trait_object!(JobExecutor); + +pub type Job = Box; + +#[async_trait] +pub trait AsyncJobExecutor: DynClone { + async fn execute(&self) -> Result<()>; +} + +clone_trait_object!(AsyncJobExecutor); + +pub type AsyncJob = Box; + +#[derive(Clone)] +pub enum TaskExecutor { + Sync(Job), + Async(AsyncJob), +} + +impl fmt::Debug for TaskExecutor { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self { + Self::Sync(_) => write!(f, "Sync"), + Self::Async(_) => write!(f, "Async"), + } + } +} + +impl From for TaskExecutor { + fn from(job: Job) -> Self { + Self::Sync(job) + } +} + +impl From for TaskExecutor { + fn from(job: AsyncJob) -> Self { + Self::Async(job) + } +} + +#[derive(Clone, Debug)] +struct DefaultJobExecutor {} + +impl JobExecutor for DefaultJobExecutor { + fn execute(&self) -> Result<()> { + unimplemented!("not implemented"); + } +} + +#[async_trait] +impl AsyncJobExecutor for DefaultJobExecutor { + async fn execute(&self) -> Result<()> { + unimplemented!("not implemented"); + } +} + +impl Default for Job { + fn default() -> Self { + Box::new(DefaultJobExecutor {}) + } +} + +impl Default for AsyncJob { + fn default() -> Self { + Box::new(DefaultJobExecutor {}) + } +} diff --git a/backend/tauri/src/core/tasks/jobs/logger.rs b/backend/tauri/src/core/tasks/jobs/logger.rs new file mode 100644 index 0000000000..b93da7a108 --- /dev/null +++ b/backend/tauri/src/core/tasks/jobs/logger.rs @@ -0,0 +1,72 @@ +use crate::config::Config; +use crate::utils::dirs; +use anyhow::Result; +use chrono::{DateTime, Local, TimeZone}; +use std::fs::{self, DirEntry}; +use std::str::FromStr; + +/// Clear logs from the logs directory +pub fn clear_logs() -> Result<()> { + let log_dir = dirs::app_logs_dir()?; + if !log_dir.exists() { + return Ok(()); + } + + let minutes = { + let verge = Config::verge(); + let verge = verge.data(); + verge.auto_log_clean.unwrap_or(0) + }; + if minutes == 0 { + return Ok(()); // 0 means disable + } + log::debug!(target: "app", "try to delete log files, minutes: {minutes}"); + + // %Y-%m-%d to NaiveDateTime + let parse_time_str = |s: &str| { + let sa: Vec<&str> = s.split('-').collect(); + if sa.len() != 4 { + return Err(anyhow::anyhow!("invalid time str")); + } + + let year = i32::from_str(sa[0])?; + let month = u32::from_str(sa[1])?; + let day = u32::from_str(sa[2])?; + let time = chrono::NaiveDate::from_ymd_opt(year, month, day) + .ok_or(anyhow::anyhow!("invalid time str"))? + .and_hms_opt(0, 0, 0) + .ok_or(anyhow::anyhow!("invalid time str"))?; + Ok(time) + }; + + let process_file = |file: DirEntry| -> Result<()> { + let file_name = file.file_name(); + let file_name = file_name.to_str().unwrap_or_default(); + + if file_name.ends_with(".log") { + let now = Local::now(); + let created_time = parse_time_str(&file_name[0..file_name.len() - 4])?; + let created_time: DateTime = Local.from_local_datetime(&created_time).unwrap(); // It is safe to use `unwrap` here because we just parsed it + + let duration = now.signed_duration_since(created_time); + if duration.num_minutes() > minutes { + let file_path = file.path(); + let _ = fs::remove_file(file_path); + log::info!(target: "app", "delete log file: {file_name}"); + } + } + Ok(()) + }; + + for file in fs::read_dir(&log_dir)? { + match file { + Ok(file) => { + let _ = process_file(file); + } + Err(err) => { + log::error!(target: "app", "read log dir error: {err}"); + } + } + } + Ok(()) +} diff --git a/backend/tauri/src/core/tasks/jobs/mod.rs b/backend/tauri/src/core/tasks/jobs/mod.rs new file mode 100644 index 0000000000..d991728487 --- /dev/null +++ b/backend/tauri/src/core/tasks/jobs/mod.rs @@ -0,0 +1 @@ +pub mod logger; diff --git a/backend/tauri/src/core/tasks/mod.rs b/backend/tauri/src/core/tasks/mod.rs new file mode 100644 index 0000000000..1b5416afcc --- /dev/null +++ b/backend/tauri/src/core/tasks/mod.rs @@ -0,0 +1,8 @@ +pub mod executor; +mod jobs; +mod records; +pub mod task; +mod utils; +/// 本模块存放一次性执行的 Job 以及定时任务 + +pub fn globals_register() {} diff --git a/backend/tauri/src/core/tasks/records.rs b/backend/tauri/src/core/tasks/records.rs new file mode 100644 index 0000000000..64cdd270ba --- /dev/null +++ b/backend/tauri/src/core/tasks/records.rs @@ -0,0 +1,77 @@ +use chrono::Utc; + +use super::task::{TaskEventID, TaskID, TaskRunResult, Timestamp}; +use std::collections::HashMap; +pub type TaskEvents = HashMap; + +pub trait TaskEventsDispatcher { + fn new() -> Self; + fn new_event(&mut self, task_id: TaskID, event_id: TaskEventID) -> TaskEventID; + fn dispatch(&mut self, event_id: TaskEventID, state: TaskEventState); +} + +impl TaskEventsDispatcher for TaskEvents { + fn new() -> Self { + HashMap::new() + } + + fn new_event(&mut self, task_id: TaskID, event_id: TaskEventID) -> TaskEventID { + let mut event = TaskEvent { + id: event_id, + task_id, + ..TaskEvent::default() + }; + event.dispatch(TaskEventState::Pending); + self.insert(event_id, event); + event_id + } + + fn dispatch(&mut self, event_id: TaskEventID, state: TaskEventState) { + let event = self.get_mut(&event_id).unwrap(); + event.dispatch(state); + } +} + +pub struct TaskEvent { + id: TaskEventID, + task_id: TaskID, + state: TaskEventState, + timeline: HashMap<&'static str, Timestamp>, +} + +pub enum TaskEventState { + Pending, // added to the queue, alias of created + Running, + Finished(TaskRunResult), + Cancelled, +} + +impl TaskEventState { + pub fn fmt(&self) -> &'static str { + match self { + Self::Pending => "pending", + Self::Running => "running", + Self::Finished(_) => "finished", + Self::Cancelled => "cancelled", + } + } +} + +impl Default for TaskEvent { + fn default() -> Self { + TaskEvent { + id: 0, + task_id: 0, + state: TaskEventState::Pending, + timeline: HashMap::with_capacity(4), // 4 states + } + } +} + +impl TaskEvent { + fn dispatch(&mut self, state: TaskEventState) { + self.state = state; + self.timeline + .insert(self.state.fmt(), Utc::now().timestamp_millis()); + } +} diff --git a/backend/tauri/src/core/tasks/store.rs b/backend/tauri/src/core/tasks/store.rs new file mode 100644 index 0000000000..e04580879a --- /dev/null +++ b/backend/tauri/src/core/tasks/store.rs @@ -0,0 +1 @@ +// store is a interface to save and restore tasks diff --git a/backend/tauri/src/core/tasks/task.rs b/backend/tauri/src/core/tasks/task.rs new file mode 100644 index 0000000000..6bdf0e92a6 --- /dev/null +++ b/backend/tauri/src/core/tasks/task.rs @@ -0,0 +1,342 @@ +use super::{ + executor::{AsyncJob, Job, TaskExecutor}, + records::{TaskEvent, TaskEvents}, +}; +use crate::error; +use anyhow::{anyhow, Context, Result}; +use chrono::Utc; +use delay_timer::{ + entity::{DelayTimer, DelayTimerBuilder}, + timer::task::TaskBuilder as TimerTaskBuilder, + utils::convenience::cron_expression_grammatical_candy::{CandyCronStr, CandyFrequency}, +}; +use once_cell::sync::OnceCell; +use serde::de; +use snowflake::SnowflakeIdGenerator; +use std::{ + collections::HashMap, + sync::{Arc, Mutex, RwLock as RW}, + time::Duration, +}; + +pub type TaskID = u64; +pub type TaskEventID = i64; // 任务事件 ID,适用于任务并发执行,区分不同的执行事件 +#[derive(Debug, Clone)] +pub enum TaskState { + Cancelled, // 任务已取消,不再执行 + Idle, // 空闲 + Running, // 任务执行中 +} + +#[derive(Debug, Clone)] +pub enum TaskRunResult { + Ok, + Err(String), +} + +#[derive(Debug, Clone)] +pub enum TaskSchedule { + Once(Duration), // 一次性执行 + Interval(Duration), // 按间隔执行 + Cron(String), // 按 cron 表达式执行 +} + +// TODO: 如果需要的话,未来可以添加执行日记(历史记录) +#[derive(Debug, Clone)] +pub struct TaskOptions { + pub maximum_parallel_runnable_num: u64, // 最大同时并发数 +} + +impl Default for TaskOptions { + fn default() -> Self { + TaskOptions { + maximum_parallel_runnable_num: 5, + } + } +} + +#[derive(Debug, Clone)] +pub struct Task { + id: TaskID, + name: String, + schedule: TaskSchedule, + state: TaskState, + opts: TaskOptions, + last_run: Option<(Timestamp, TaskRunResult)>, + next_run: Option, // timestamp + executor: TaskExecutor, + created_at: Timestamp, +} + +impl Default for Task { + fn default() -> Self { + Task { + id: 0, + name: String::new(), + schedule: TaskSchedule::Once(Duration::from_secs(0)), + state: TaskState::Idle, + opts: TaskOptions::default(), + executor: TaskExecutor::Sync(Job::default()), // a unimplemented job + last_run: None, + next_run: None, + created_at: 0, + } + } +} + +pub type Timestamp = i64; + +// 检查任务输入 +macro_rules! check_task_input { + ($task:ident) => { + if $task.name.is_empty() { + return Err(anyhow!("task name is empty")); + } + + match &$task.schedule { + TaskSchedule::Once(duration) => { + if duration.as_secs() <= 0 { + return Err(anyhow!("task interval must be greater than 0")); + } + } + TaskSchedule::Interval(duration) => { + if duration.as_secs() <= 0 { + return Err(anyhow!("task interval must be greater than 0")); + } + } + TaskSchedule::Cron(cron) => { + if cron.is_empty() { + return Err(anyhow!("task cron is empty")); + } + } + } + }; +} + +// 构建任务 +fn build_task<'a>(task: Task, len: usize) -> (Task, TimerTaskBuilder<'a>) { + let task = Task { + id: match task.id { + 0 => len as u64 + 1, + _ => task.id, + }, + created_at: match task.created_at { + 0 => Utc::now().timestamp(), + _ => task.created_at, + }, + ..task + }; + + let mut builder = TimerTaskBuilder::default(); + builder.set_task_id(task.id); + + match &task.schedule { + TaskSchedule::Cron(cron) => { + // NOTE: 由于 DelayTimer 的垃圾设计,因此继续使用弃用的 candy 方法 + // NOTE: 请注意一定需要回收内存,否则会造成内存泄漏 + let cron = cron.clone(); + builder.set_frequency_by_candy(CandyFrequency::Repeated(CandyCronStr(cron))); + } + TaskSchedule::Interval(duration) => { + builder.set_frequency_repeated_by_seconds(duration.as_secs()); + } + // 一次性延迟任务,目前设计只支持 Interval + // TODO: 支持即时任务? + TaskSchedule::Once(duration) => { + builder.set_frequency_once_by_seconds(duration.as_secs()); + } + } + + builder.set_maximum_parallel_runnable_num(task.opts.maximum_parallel_runnable_num); // 最大同时并发数 + + (task, builder) +} + +fn wrap_job(list: TaskList, task_id: TaskID, job: Job) { + let _ = list.set_task_state(task_id, TaskState::Running, None); + let res = job.execute(); + let _ = list.set_task_state( + task_id, + TaskState::Idle, + Some(match res { + Ok(_) => TaskRunResult::Ok, + Err(e) => { + error!(format!("task error: {}", e.to_string())); + TaskRunResult::Err(e.to_string()) + } + }), + ); +} + +async fn wrap_async_job(list: TaskList, task_id: TaskID, async_job: AsyncJob) { + let _ = list.set_task_state(task_id, TaskState::Running, None); + let res = async_job.execute().await; + let _ = list.set_task_state( + task_id, + TaskState::Idle, + Some(match res { + Ok(_) => TaskRunResult::Ok, + Err(e) => { + error!(format!("task error: {}", e.to_string())); + TaskRunResult::Err(e.to_string()) + } + }), + ); +} + +// TaskList 语法糖 +type TaskList = Arc>>; +trait TaskListOps { + fn set_task_state( + &self, + task_id: TaskID, + state: TaskState, + result: Option, + ) -> Result<()>; +} +impl TaskListOps for TaskList { + fn set_task_state( + &self, + task_id: TaskID, + state: TaskState, + result: Option, + ) -> Result<()> { + let mut list = self.write().unwrap(); + let item = list + .iter_mut() + .find(|t| t.id == task_id) + .ok_or(anyhow!("task {} not found", task_id))?; + match state { + TaskState::Running => { + item.state = TaskState::Running; + } + TaskState::Idle => { + if let TaskState::Running = item.state { + item.last_run = Some(( + Utc::now().timestamp(), + result.ok_or(anyhow!( + "change task {} state from running to idle, but result is none", + task_id + ))?, + )); + } + item.state = TaskState::Idle; + } + TaskState::Cancelled => { + item.state = TaskState::Cancelled; + } + } + Ok(()) + } +} + +type TasksEvents = Arc>>; + +pub struct TaskManager { + /// cron manager + timer: Arc>, + + /// task list + list: TaskList, + + id_generator: SnowflakeIdGenerator, + events: TasksEvents, // 任务事件 +} + +impl TaskManager { + pub fn globals() -> &'static Self { + static TASK_MANAGER: OnceCell = OnceCell::new(); + + TASK_MANAGER.get_or_init(|| TaskManager { + timer: Arc::new(Mutex::new(DelayTimerBuilder::default().build())), + list: Arc::new(RW::new(Vec::new())), + id_generator: SnowflakeIdGenerator::new(1, 1), + events: Arc::new(RW::new(HashMap::new())), + }) + } + + /// add task + /// + /// # Example + /// ```rust + /// let task = Task { + /// name: "test".to_string(), + /// schedule: TaskSchedule::Once(Duration::from_secs(1)), + /// ..Task::default() + /// }; + /// let job = Job::default(); + /// task_manager.add_task(task, job.into()); + pub fn add_task(&mut self, task: Task) -> Result<()> { + check_task_input!(task); + let (task, mut builder) = { + let list = self.list.read().unwrap(); + build_task(task, list.len()) + }; + + + let task_id = task.id; + let list_ref = self.list.clone(); + let executor = task.executor.clone(); + let timer_task = match executor { + TaskExecutor::Sync(job) => { + let body = move || { + let list = list_ref.clone(); + wrap_job(list, task_id, job.clone()) + }; + builder.spawn_routine(body) + } + TaskExecutor::Async(async_job) => { + let body = move || { + let list = list_ref.clone(); + let async_job = async_job.clone(); + async move { wrap_async_job(list, task_id, async_job).await } + }; + + builder.spawn_async_routine(body) + } + }; + + { + builder.free(); // 在错误处理之前,先释放内存 + } + + let timer = self.timer.lock().unwrap(); + let mut list = self.list.write().unwrap(); + timer + .add_task(timer_task.context("failed to build a task")?) + .context("failed to add a task to scheduler")?; + list.push(task); + Ok(()) + } + + pub fn pick_task(&self, task_id: TaskID) -> Result { + let list = self.list.read().unwrap(); + list.iter() + .find(|t| t.id == task_id) + .cloned() + .ok_or(anyhow!("task {} not found", task_id)) + } + + pub fn total(&self) -> usize { + let list = self.list.read().unwrap(); + list.len() + } + + // get current task list + // note: this method will clone the task list + pub fn list(&self) -> Vec { + let list = self.list.read().unwrap(); + list.clone() + } + + pub fn remove_task(&mut self, task_id: TaskID) -> Result<()> { + let mut list = self.list.write().unwrap(); + let index = list + .iter() + .position(|t| t.id == task_id) + .ok_or(anyhow!("task {} not found", task_id))?; + self.timer.lock().unwrap().remove_task(task_id)?; + list.remove(index); + Ok(()) + } +} diff --git a/backend/tauri/src/core/tasks/utils.rs b/backend/tauri/src/core/tasks/utils.rs new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/backend/tauri/src/core/tasks/utils.rs @@ -0,0 +1 @@ + diff --git a/backend/tauri/src/utils/dirs.rs b/backend/tauri/src/utils/dirs.rs index 696831de86..e9dbd6afc7 100644 --- a/backend/tauri/src/utils/dirs.rs +++ b/backend/tauri/src/utils/dirs.rs @@ -13,6 +13,7 @@ static APP_DIR: &str = "clash-verge-dev"; static CLASH_CONFIG: &str = "config.yaml"; static VERGE_CONFIG: &str = "verge.yaml"; static PROFILE_YAML: &str = "profiles.yaml"; +static STORAGE_DB: &str = "storage.db"; static mut RESOURCE_DIR: Option = None; @@ -107,6 +108,10 @@ pub fn profiles_path() -> Result { Ok(app_home_dir()?.join(PROFILE_YAML)) } +pub fn storage_path() -> Result { + Ok(app_home_dir()?.join(STORAGE_DB)) +} + #[allow(unused)] pub fn app_res_dir() -> Result { unsafe { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a6abd7f508..836e51bf3c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,7 +52,7 @@ dependencies: version: 10.16.16(react-dom@18.2.0)(react@18.2.0) i18next: specifier: ^23.0.0 - version: 23.7.9 + version: 23.0.0 lodash-es: specifier: ^4.17.21 version: 4.17.21 @@ -67,13 +67,13 @@ dependencies: version: 18.2.0(react@18.2.0) react-error-boundary: specifier: ^4.0.0 - version: 4.0.11(react@18.2.0) + version: 4.0.0(react@18.2.0) react-hook-form: specifier: ^7.39.5 version: 7.39.5(react@18.2.0) react-i18next: specifier: ^13.0.0 - version: 13.5.0(i18next@23.7.9)(react-dom@18.2.0)(react@18.2.0) + version: 13.0.0(i18next@23.0.0)(react-dom@18.2.0)(react@18.2.0) react-router-dom: specifier: ^6.4.3 version: 6.4.3(react-dom@18.2.0)(react@18.2.0) @@ -82,7 +82,7 @@ dependencies: version: 4.4.5(react-dom@18.2.0)(react@18.2.0) react-virtuoso: specifier: ^4.0.0 - version: 4.6.2(react-dom@18.2.0)(react@18.2.0) + version: 4.0.0(react-dom@18.2.0)(react@18.2.0) recoil: specifier: ^0.7.6 version: 0.7.6(react-dom@18.2.0)(react@18.2.0) @@ -91,7 +91,7 @@ dependencies: version: 2.0.0 swr: specifier: ^2.0.0 - version: 2.2.4(react@18.2.0) + version: 2.0.0(react@18.2.0) devDependencies: '@actions/github': @@ -108,7 +108,7 @@ devDependencies: version: 1.5.7 '@types/fs-extra': specifier: ^11.0.0 - version: 11.0.4 + version: 11.0.0 '@types/js-cookie': specifier: ^3.0.2 version: 3.0.2 @@ -135,7 +135,7 @@ devDependencies: version: 6.14.0(eslint@8.55.0)(typescript@5.3.2) '@vitejs/plugin-react': specifier: ^4.1.0 - version: 4.1.0(vite@5.0.8) + version: 4.1.0(vite@5.0.0) adm-zip: specifier: ^0.5.9 version: 0.5.9 @@ -186,10 +186,10 @@ devDependencies: version: 11.2.0 https-proxy-agent: specifier: ^7.0.0 - version: 7.0.2 + version: 7.0.0 husky: specifier: ^8.0.0 - version: 8.0.3 + version: 8.0.0 lint-staged: specifier: 15.2.0 version: 15.2.0 @@ -255,13 +255,13 @@ devDependencies: version: 5.3.2 vite: specifier: ^5.0.0 - version: 5.0.8(@types/node@18.19.0)(sass@1.54.8) + version: 5.0.0(@types/node@18.19.0)(sass@1.54.8) vite-plugin-monaco-editor: specifier: ^1.1.0 version: 1.1.0(monaco-editor@0.45.0) vite-plugin-svgr: specifier: ^4.1.0 - version: 4.1.0(typescript@5.3.2)(vite@5.0.8) + version: 4.1.0(typescript@5.3.2)(vite@5.0.0) packages: @@ -763,7 +763,7 @@ packages: resolution: {integrity: sha512-m4HEDZleaaCH+XgDDsPF15Ht6wTLsgDTeR3WYj9Q/k76JtWhrJjcP4+/XlG8LGT/Rol9qUfOIztXeA84ATpqPQ==} dependencies: '@babel/helper-module-imports': 7.22.15 - '@babel/runtime': 7.23.5 + '@babel/runtime': 7.23.2 '@emotion/hash': 0.9.1 '@emotion/memoize': 0.8.1 '@emotion/serialize': 1.1.2 @@ -1431,7 +1431,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.5 + '@babel/runtime': 7.23.2 '@floating-ui/react-dom': 2.0.2(react-dom@18.2.0)(react@18.2.0) '@mui/types': 7.2.6(@types/react@18.2.37) '@mui/utils': 5.14.14(@types/react@18.2.37)(react@18.2.0) @@ -1650,7 +1650,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.5 + '@babel/runtime': 7.23.2 '@emotion/react': 11.11.1(@types/react@18.2.37)(react@18.2.0) '@emotion/styled': 11.11.0(@emotion/react@11.11.1)(@types/react@18.2.37)(react@18.2.0) '@mui/private-theming': 5.14.14(@types/react@18.2.37)(react@18.2.0) @@ -1726,7 +1726,7 @@ packages: '@types/react': optional: true dependencies: - '@babel/runtime': 7.23.5 + '@babel/runtime': 7.23.2 '@types/prop-types': 15.7.9 '@types/react': 18.2.37 prop-types: 15.8.1 @@ -2299,8 +2299,8 @@ packages: resolution: {integrity: sha512-CS2rOaoQ/eAgAfcTfq6amKG7bsN+EMcgGY4FAFQdvSj2y1ixvOZTUA9mOtCai7E1SYu283XNw7urKK30nP3wkQ==} dev: true - /@types/fs-extra@11.0.4: - resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + /@types/fs-extra@11.0.0: + resolution: {integrity: sha512-zdV5odfHf95B4qr6bdpshG4VMm/3xgnPhSJLa3xh75CYr35e34k+4FQli82Q48sPqwHazJGy+6+jl4T+Vw1AMg==} dependencies: '@types/jsonfile': 6.1.4 '@types/node': 18.19.0 @@ -2527,7 +2527,7 @@ packages: resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} dev: true - /@vitejs/plugin-react@4.1.0(vite@5.0.8): + /@vitejs/plugin-react@4.1.0(vite@5.0.0): resolution: {integrity: sha512-rM0SqazU9iqPUraQ2JlIvReeaxOoRj6n+PzB1C0cBzIbd8qP336nC39/R9yPi3wVcah7E7j/kdU1uCUqMEU4OQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -2538,7 +2538,7 @@ packages: '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.23.2) '@types/babel__core': 7.20.3 react-refresh: 0.14.0 - vite: 5.0.8(@types/node@18.19.0)(sass@1.54.8) + vite: 5.0.0(@types/node@18.19.0)(sass@1.54.8) transitivePeerDependencies: - supports-color dev: true @@ -2982,10 +2982,6 @@ packages: string-width: 7.0.0 dev: true - /client-only@0.0.1: - resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} - dev: false - /cliui@8.0.1: resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} engines: {node: '>=12'} @@ -3329,7 +3325,7 @@ packages: /dom-helpers@5.2.1: resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==} dependencies: - '@babel/runtime': 7.23.5 + '@babel/runtime': 7.23.2 csstype: 3.1.2 dev: false @@ -4381,8 +4377,8 @@ packages: entities: 4.5.0 dev: true - /https-proxy-agent@7.0.2: - resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + /https-proxy-agent@7.0.0: + resolution: {integrity: sha512-0euwPCRyAPSgGdzD1IVN9nJYHtBhJwb6XPfbpQcYbPCwrBidX6GzxmchnaF4sfF/jPb74Ojx5g4yTg3sixlyPw==} engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 @@ -4411,14 +4407,14 @@ packages: engines: {node: '>=16.17.0'} dev: true - /husky@8.0.3: - resolution: {integrity: sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==} + /husky@8.0.0: + resolution: {integrity: sha512-4qbE/5dzNDNxFEkX9MNRPKl5+omTXQzdILCUWiqG/lWIAioiM5vln265/l6I2Zx8gpW8l1ukZwGQeCFbBZ6+6w==} engines: {node: '>=14'} hasBin: true dev: true - /i18next@23.7.9: - resolution: {integrity: sha512-wturtxTfJLJdLzHhyfxXo2l9Cbu2Iz4wF4065oWThPvdFJMUUG3fhXD3BLCHgrv4VxfScORq0i9sfCdjVPbgiw==} + /i18next@23.0.0: + resolution: {integrity: sha512-nwggKtf7ZQWq1t21qGUGhrwoyRWHJNTy016jOPl6ZDfxGZAUyK1FWm3EgELgfO4ujNifCHmxJ6pyDdcX7cagWg==} dependencies: '@babel/runtime': 7.23.5 dev: false @@ -5642,8 +5638,8 @@ packages: scheduler: 0.23.0 dev: false - /react-error-boundary@4.0.11(react@18.2.0): - resolution: {integrity: sha512-U13ul67aP5DOSPNSCWQ/eO0AQEYzEFkVljULQIjMV0KlffTAhxuDoBKdO0pb/JZ8mDhMKFZ9NZi0BmLGUiNphw==} + /react-error-boundary@4.0.0(react@18.2.0): + resolution: {integrity: sha512-vNbTyivmwBxCpJA68Ry55rJhZMzJSB+egkEm8hkEzbEBJLsJp5054zEVpoK/8ndxt6B+dvEA2LDw33xUfvE8og==} peerDependencies: react: '>=16.13.1' dependencies: @@ -5660,10 +5656,10 @@ packages: react: 18.2.0 dev: false - /react-i18next@13.5.0(i18next@23.7.9)(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-CFJ5NDGJ2MUyBohEHxljOq/39NQ972rh1ajnadG9BjTk+UXbHLq4z5DKEbEQBDoIhUmmbuS/fIMJKo6VOax1HA==} + /react-i18next@13.0.0(i18next@23.0.0)(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-qRFbrSgynsBSjfnSTb/Um3mw9uPjOfDi4Iq2rMCuzfsRsYGdkEdyCr0i+T0bR0bG6xwULvK4k1oRVLLd7ZDBVw==} peerDependencies: - i18next: '>= 23.2.3' + i18next: '>= 23.0.1' react: '>= 16.8.0' react-dom: '*' react-native: '*' @@ -5675,7 +5671,7 @@ packages: dependencies: '@babel/runtime': 7.23.5 html-parse-stringify: 3.0.1 - i18next: 23.7.9 + i18next: 23.0.0 react: 18.2.0 react-dom: 18.2.0(react@18.2.0) dev: false @@ -5729,8 +5725,8 @@ packages: react-dom: 18.2.0(react@18.2.0) dev: false - /react-virtuoso@4.6.2(react-dom@18.2.0)(react@18.2.0): - resolution: {integrity: sha512-vvlqvzPif+MvBrJ09+hJJrVY0xJK9yran+A+/1iwY78k0YCVKsyoNPqoLxOxzYPggspNBNXqUXEcvckN29OxyQ==} + /react-virtuoso@4.0.0(react-dom@18.2.0)(react@18.2.0): + resolution: {integrity: sha512-gYksvHWVuJUhKbHR1nLQXmChmcnwglbPfzZzsxsz1p7MxvXR6Ax4DR+RL1AoeT+YAnMhpeskVxUsjgpeyXgYJw==} engines: {node: '>=10'} peerDependencies: react: '>=16 || >=17 || >= 18' @@ -6448,12 +6444,12 @@ packages: resolution: {integrity: sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==} dev: true - /swr@2.2.4(react@18.2.0): - resolution: {integrity: sha512-njiZ/4RiIhoOlAaLYDqwz5qH/KZXVilRLvomrx83HjzCWTfa+InyfAjv05PSFxnmLzZkNO9ZfvgoqzAaEI4sGQ==} + /swr@2.0.0(react@18.2.0): + resolution: {integrity: sha512-IhUx5yPkX+Fut3h0SqZycnaNLXLXsb2ECFq0Y29cxnK7d8r7auY2JWNbCW3IX+EqXUg3rwNJFlhrw5Ye/b6k7w==} + engines: {pnpm: '7'} peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 dependencies: - client-only: 0.0.1 react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) dev: false @@ -6708,7 +6704,7 @@ packages: monaco-editor: 0.45.0 dev: true - /vite-plugin-svgr@4.1.0(typescript@5.3.2)(vite@5.0.8): + /vite-plugin-svgr@4.1.0(typescript@5.3.2)(vite@5.0.0): resolution: {integrity: sha512-v7Qic+FWmCChgQNGSI4V8X63OEYsdUoLt66iqIcHozq9bfK/Dwmr0V+LBy1NE8CE98Y8HouEBJ+pto4AMfN5xw==} peerDependencies: vite: ^2.6.0 || 3 || 4 @@ -6716,15 +6712,15 @@ packages: '@rollup/pluginutils': 5.0.5 '@svgr/core': 8.1.0(typescript@5.3.2) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0) - vite: 5.0.8(@types/node@18.19.0)(sass@1.54.8) + vite: 5.0.0(@types/node@18.19.0)(sass@1.54.8) transitivePeerDependencies: - rollup - supports-color - typescript dev: true - /vite@5.0.8(@types/node@18.19.0)(sass@1.54.8): - resolution: {integrity: sha512-jYMALd8aeqR3yS9xlHd0OzQJndS9fH5ylVgWdB+pxTwxLKdO1pgC5Dlb398BUxpfaBxa4M9oT7j1g503Gaj5IQ==} + /vite@5.0.0(@types/node@18.19.0)(sass@1.54.8): + resolution: {integrity: sha512-ESJVM59mdyGpsiNAeHQOR/0fqNoOyWPYesFto8FFZugfmhdHx8Fzd8sF3Q/xkVhZsyOxHfdM7ieiVAorI9RjFw==} engines: {node: ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: