diff --git a/.gitignore b/.gitignore index 6c40725a..408aecad 100644 --- a/.gitignore +++ b/.gitignore @@ -54,3 +54,6 @@ apps/frontend/src/generated .turbo target generated + +# app testing dir +app-playground-data/* \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 1110eb7b..c9b44ce0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -28,6 +28,19 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "getrandom 0.2.15", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -52,6 +65,12 @@ dependencies = [ "alloc-no-stdlib", ] +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + [[package]] name = "android-tzdata" version = "0.1.1" @@ -318,6 +337,15 @@ dependencies = [ "system-deps 6.2.2", ] +[[package]] +name = "atoi" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" +dependencies = [ + "num-traits", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -384,25 +412,6 @@ dependencies = [ "serde", ] -[[package]] -name = "bincode" -version = "2.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11ea1a0346b94ef188834a65c068a03aec181c94896d481d7a0a40d85b0ce95" -dependencies = [ - "bincode_derive", - "serde", -] - -[[package]] -name = "bincode_derive" -version = "2.0.0-rc.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e30759b3b99a1b802a7a3aa21c85c3ded5c28e1c83170d82d70f08bbf7f3e4c" -dependencies = [ - "virtue", -] - [[package]] name = "bitflags" version = "1.3.2" @@ -414,6 +423,9 @@ name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +dependencies = [ + "serde", +] [[package]] name = "block" @@ -845,6 +857,21 @@ dependencies = [ "parking_lot", ] +[[package]] +name = "crc" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" +dependencies = [ + "crc-catalog", +] + +[[package]] +name = "crc-catalog" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" + [[package]] name = "crc32fast" version = "1.4.2" @@ -882,6 +909,15 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "crossbeam-queue" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-utils" version = "0.8.20" @@ -949,19 +985,15 @@ dependencies = [ [[package]] name = "daedalus" -version = "0.1.27" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b251eb4ed1dd9c417eb098492dcf17f8271ba5722387ffa3ee703bcebdb4838" +checksum = "7b8590e725889bb981febb438f133f8ef6b62f610f92835c961338e771222b1a" dependencies = [ - "bincode 2.0.0-rc.3", "bytes", "chrono", - "reqwest 0.11.27", "serde", "serde_json", - "sha1 0.6.1", "thiserror", - "tokio", ] [[package]] @@ -999,6 +1031,21 @@ dependencies = [ "syn 2.0.71", ] +[[package]] +name = "dashmap" +version = "6.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804c8821570c3f8b70230c2ba75ffa5c0f9a4189b9a432b6656c536712acae28" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", + "serde", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -1138,6 +1185,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "dotenvy" +version = "0.15.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" + [[package]] name = "dtoa" version = "1.0.9" @@ -1178,6 +1231,9 @@ name = "either" version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" +dependencies = [ + "serde", +] [[package]] name = "elliptic-curve" @@ -1271,6 +1327,17 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "etcetera" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" +dependencies = [ + "cfg-if", + "home", + "windows-sys 0.48.0", +] + [[package]] name = "event-listener" version = "2.5.3" @@ -1387,6 +1454,17 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "flume" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" +dependencies = [ + "futures-core", + "futures-sink", + "spin", +] + [[package]] name = "fnv" version = "1.0.7" @@ -1505,6 +1583,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-intrusive" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" +dependencies = [ + "futures-core", + "lock_api", + "parking_lot", +] + [[package]] name = "futures-io" version = "0.3.30" @@ -1909,25 +1998,6 @@ dependencies = [ "syn 1.0.109", ] -[[package]] -name = "h2" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" -dependencies = [ - "bytes", - "fnv", - "futures-core", - "futures-sink", - "futures-util", - "http 0.2.12", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "h2" version = "0.4.5" @@ -1958,6 +2028,19 @@ name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashlink" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" +dependencies = [ + "hashbrown 0.14.5", +] [[package]] name = "heck" @@ -1973,6 +2056,9 @@ name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +dependencies = [ + "unicode-segmentation", +] [[package]] name = "heck" @@ -1998,6 +2084,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hkdf" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" +dependencies = [ + "hmac", +] + [[package]] name = "hmac" version = "0.12.1" @@ -2063,17 +2158,6 @@ dependencies = [ "itoa 1.0.11", ] -[[package]] -name = "http-body" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" -dependencies = [ - "bytes", - "http 0.2.12", - "pin-project-lite", -] - [[package]] name = "http-body" version = "1.0.1" @@ -2093,7 +2177,7 @@ dependencies = [ "bytes", "futures-util", "http 1.1.0", - "http-body 1.0.1", + "http-body", "pin-project-lite", ] @@ -2115,30 +2199,6 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" -[[package]] -name = "hyper" -version = "0.14.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" -dependencies = [ - "bytes", - "futures-channel", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "httparse", - "httpdate", - "itoa 1.0.11", - "pin-project-lite", - "socket2 0.5.7", - "tokio", - "tower-service", - "tracing", - "want", -] - [[package]] name = "hyper" version = "1.4.1" @@ -2148,9 +2208,9 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", + "h2", "http 1.1.0", - "http-body 1.0.1", + "http-body", "httparse", "itoa 1.0.11", "pin-project-lite", @@ -2167,7 +2227,7 @@ checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.4.1", + "hyper", "hyper-util", "rustls", "rustls-pki-types", @@ -2176,19 +2236,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.30", - "native-tls", - "tokio", - "tokio-native-tls", -] - [[package]] name = "hyper-tls" version = "0.6.0" @@ -2197,7 +2244,7 @@ checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ "bytes", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-util", "native-tls", "tokio", @@ -2215,8 +2262,8 @@ dependencies = [ "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.1", - "hyper 1.4.1", + "http-body", + "hyper", "pin-project-lite", "socket2 0.5.7", "tokio", @@ -2552,6 +2599,9 @@ name = "lazy_static" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +dependencies = [ + "spin", +] [[package]] name = "libc" @@ -2559,6 +2609,12 @@ version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "libredox" version = "0.1.3" @@ -2569,6 +2625,17 @@ dependencies = [ "libc", ] +[[package]] +name = "libsqlite3-sys" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f" +dependencies = [ + "cc", + "pkg-config", + "vcpkg", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -2676,6 +2743,16 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" +[[package]] +name = "md-5" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" +dependencies = [ + "cfg-if", + "digest", +] + [[package]] name = "memchr" version = "2.7.4" @@ -2784,6 +2861,12 @@ dependencies = [ "uuid 1.10.0", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.7.4" @@ -2887,6 +2970,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "notify" version = "6.1.1" @@ -2935,6 +3028,23 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand 0.8.5", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -2952,6 +3062,26 @@ dependencies = [ "syn 2.0.71", ] +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -2959,6 +3089,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3086,9 +3217,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "c2823eb4c6453ed64055057ea8bd416eda38c71018723869dd043a3b1186115e" dependencies = [ "bitflags 2.6.0", "cfg-if", @@ -3118,9 +3249,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -3454,6 +3585,17 @@ dependencies = [ "futures-io", ] +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + [[package]] name = "pkcs8" version = "0.10.2" @@ -3535,9 +3677,9 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "powerfmt" @@ -3832,46 +3974,6 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" -[[package]] -name = "reqwest" -version = "0.11.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" -dependencies = [ - "base64 0.21.7", - "bytes", - "encoding_rs", - "futures-core", - "futures-util", - "h2 0.3.26", - "http 0.2.12", - "http-body 0.4.6", - "hyper 0.14.30", - "hyper-tls 0.5.0", - "ipnet", - "js-sys", - "log", - "mime", - "native-tls", - "once_cell", - "percent-encoding", - "pin-project-lite", - "rustls-pemfile 1.0.4", - "serde", - "serde_json", - "serde_urlencoded", - "sync_wrapper 0.1.2", - "system-configuration", - "tokio", - "tokio-native-tls", - "tower-service", - "url", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "winreg 0.50.0", -] - [[package]] name = "reqwest" version = "0.12.5" @@ -3885,13 +3987,13 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.4.5", + "h2", "http 1.1.0", - "http-body 1.0.1", + "http-body", "http-body-util", - "hyper 1.4.1", + "hyper", "hyper-rustls", - "hyper-tls 0.6.0", + "hyper-tls", "hyper-util", "ipnet", "js-sys", @@ -3901,11 +4003,11 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls-pemfile 2.1.2", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper 1.0.1", + "sync_wrapper", "system-configuration", "tokio", "tokio-native-tls", @@ -3974,6 +4076,26 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core 0.6.4", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -4029,15 +4151,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "rustls-pemfile" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" -dependencies = [ - "base64 0.21.7", -] - [[package]] name = "rustls-pemfile" version = "2.1.2" @@ -4201,7 +4314,7 @@ checksum = "00421ed8fa0c995f07cde48ba6c89e80f2b312f74ff637326f392fbfd23abe02" dependencies = [ "httpdate", "native-tls", - "reqwest 0.12.5", + "reqwest", "sentry-backtrace", "sentry-contexts", "sentry-core", @@ -4449,15 +4562,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - [[package]] name = "sha1" version = "0.10.6" @@ -4540,6 +4644,9 @@ name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +dependencies = [ + "serde", +] [[package]] name = "smart-default" @@ -4605,6 +4712,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" @@ -4616,6 +4726,202 @@ dependencies = [ "der", ] +[[package]] +name = "sqlformat" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f895e3734318cc55f1fe66258926c9b910c124d47520339efecbb6c59cec7c1f" +dependencies = [ + "nom", + "unicode_categories", +] + +[[package]] +name = "sqlx" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "sqlx-core", + "sqlx-macros", + "sqlx-mysql", + "sqlx-postgres", + "sqlx-sqlite", +] + +[[package]] +name = "sqlx-core" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "ahash", + "atoi", + "byteorder", + "bytes", + "crc", + "crossbeam-queue", + "either", + "event-listener 2.5.3", + "futures-channel", + "futures-core", + "futures-intrusive", + "futures-io", + "futures-util", + "hashlink", + "hex", + "indexmap 2.2.6", + "log", + "memchr", + "once_cell", + "paste", + "percent-encoding", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlformat", + "thiserror", + "tokio", + "tokio-stream", + "tracing", + "url", +] + +[[package]] +name = "sqlx-macros" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "proc-macro2", + "quote", + "sqlx-core", + "sqlx-macros-core", + "syn 2.0.71", +] + +[[package]] +name = "sqlx-macros-core" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "dotenvy", + "either", + "heck 0.4.1", + "hex", + "once_cell", + "proc-macro2", + "quote", + "serde", + "serde_json", + "sha2", + "sqlx-core", + "sqlx-mysql", + "sqlx-sqlite", + "syn 2.0.71", + "tempfile", + "tokio", + "url", +] + +[[package]] +name = "sqlx-mysql" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "atoi", + "base64 0.21.7", + "bitflags 2.6.0", + "byteorder", + "bytes", + "crc", + "digest", + "dotenvy", + "either", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "generic-array", + "hex", + "hkdf", + "hmac", + "itoa 1.0.11", + "log", + "md-5", + "memchr", + "once_cell", + "percent-encoding", + "rand 0.8.5", + "rsa", + "serde", + "sha1", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-postgres" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "atoi", + "base64 0.21.7", + "bitflags 2.6.0", + "byteorder", + "crc", + "dotenvy", + "etcetera", + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "hex", + "hkdf", + "hmac", + "home", + "itoa 1.0.11", + "log", + "md-5", + "memchr", + "once_cell", + "rand 0.8.5", + "serde", + "serde_json", + "sha2", + "smallvec", + "sqlx-core", + "stringprep", + "thiserror", + "tracing", + "whoami", +] + +[[package]] +name = "sqlx-sqlite" +version = "0.8.0-alpha.0" +source = "git+https://github.com/launchbadge/sqlx.git?rev=352b02de6af70f1ff1bfbd15329120589a0f7337#352b02de6af70f1ff1bfbd15329120589a0f7337" +dependencies = [ + "atoi", + "flume", + "futures-channel", + "futures-core", + "futures-executor", + "futures-intrusive", + "futures-util", + "libsqlite3-sys", + "log", + "percent-encoding", + "serde", + "sqlx-core", + "tracing", + "url", + "urlencoding", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -4663,6 +4969,17 @@ dependencies = [ "quote", ] +[[package]] +name = "stringprep" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" +dependencies = [ + "unicode-bidi", + "unicode-normalization", + "unicode-properties", +] + [[package]] name = "strsim" version = "0.11.1" @@ -4697,12 +5014,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "sync_wrapper" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" - [[package]] name = "sync_wrapper" version = "1.0.1" @@ -5015,7 +5326,7 @@ name = "tauri-plugin-window-state" version = "0.1.1" source = "git+https://github.com/tauri-apps/plugins-workspace?branch=v1#a3fe84296a9a51fed960ab99ee7cebebb7df5390" dependencies = [ - "bincode 1.3.3", + "bincode", "bitflags 2.6.0", "log", "serde", @@ -5130,7 +5441,7 @@ dependencies = [ [[package]] name = "theseus" -version = "0.7.2" +version = "0.0.0" dependencies = [ "async-recursion", "async-tungstenite", @@ -5140,6 +5451,7 @@ dependencies = [ "bytes", "chrono", "daedalus", + "dashmap", "dirs", "discord-rich-presence", "dunce", @@ -5153,17 +5465,17 @@ dependencies = [ "paste", "rand 0.8.5", "regex", - "reqwest 0.12.5", + "reqwest", "serde", "serde_ini", "serde_json", "sha1_smol", "sha2", + "sqlx", "sys-info", "sysinfo", "tauri", "tempfile", - "theseus_macros", "thiserror", "tokio", "tokio-stream", @@ -5182,17 +5494,19 @@ dependencies = [ [[package]] name = "theseus_gui" -version = "0.7.2" +version = "0.0.0" dependencies = [ "chrono", "cocoa 0.25.0", "daedalus", + "dashmap", "dirs", "futures", "lazy_static", "objc", "once_cell", "os_info", + "paste", "sentry", "sentry-rust-minidump", "serde", @@ -5213,19 +5527,10 @@ dependencies = [ "window-shadows", ] -[[package]] -name = "theseus_macros" -version = "0.1.0" -dependencies = [ - "quote", - "syn 2.0.71", -] - [[package]] name = "theseus_playground" version = "0.0.0" dependencies = [ - "daedalus", "dunce", "futures", "serde", @@ -5472,7 +5777,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.14", ] [[package]] @@ -5508,6 +5813,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5606,7 +5912,7 @@ dependencies = [ "log", "native-tls", "rand 0.8.5", - "sha1 0.10.6", + "sha1", "thiserror", "url", "utf-8", @@ -5668,6 +5974,12 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "unicode-properties" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4259d9d4425d9f0661581b804cb85fe66a4c631cadd8f490d1c13a35d5d9291" + [[package]] name = "unicode-segmentation" version = "1.11.0" @@ -5680,6 +5992,12 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +[[package]] +name = "unicode_categories" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" + [[package]] name = "untrusted" version = "0.9.0" @@ -5772,12 +6090,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "virtue" -version = "0.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dcc60c0624df774c82a0ef104151231d37da4962957d691c011c852b2473314" - [[package]] name = "void" version = "1.0.2" @@ -6479,9 +6791,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" dependencies = [ "memchr", ] @@ -6625,7 +6937,7 @@ dependencies = [ "rand 0.8.5", "serde", "serde_repr", - "sha1 0.10.6", + "sha1", "static_assertions", "tracing", "uds_windows", @@ -6661,6 +6973,26 @@ dependencies = [ "zvariant", ] +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.71", +] + [[package]] name = "zeroize" version = "1.8.1" @@ -6682,7 +7014,7 @@ dependencies = [ "flate2", "hmac", "pbkdf2", - "sha1 0.10.6", + "sha1", "time", "zstd 0.11.2+zstd.1.5.2", ] diff --git a/Cargo.toml b/Cargo.toml index 5713c74b..94f58399 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,6 @@ resolver = '2' members = [ './packages/app-lib', - './packages/app-macros', './apps/app-playground', './apps/app' ] @@ -14,3 +13,6 @@ codegen-units = 1 # Compile crates one after another so the compiler can optimiz lto = true # Enables link to optimizations opt-level = "s" # Optimize for binary size strip = true # Remove debug symbols + +[profile.dev.package.sqlx-macros] +opt-level = 3 diff --git a/apps/app-frontend/package.json b/apps/app-frontend/package.json index 4db53d4a..e7d5ec9a 100644 --- a/apps/app-frontend/package.json +++ b/apps/app-frontend/package.json @@ -1,7 +1,7 @@ { "name": "@modrinth/app-frontend", "private": true, - "version": "0.7.2", + "version": "0.0.0", "type": "module", "scripts": { "dev": "vite", diff --git a/apps/app-frontend/src/App.vue b/apps/app-frontend/src/App.vue index d7404b1a..5ba7311c 100644 --- a/apps/app-frontend/src/App.vue +++ b/apps/app-frontend/src/App.vue @@ -1,5 +1,5 @@ diff --git a/apps/app-frontend/src/components/ui/RunningAppBar.vue b/apps/app-frontend/src/components/ui/RunningAppBar.vue index 02b0e3ac..6638db80 100644 --- a/apps/app-frontend/src/components/ui/RunningAppBar.vue +++ b/apps/app-frontend/src/components/ui/RunningAppBar.vue @@ -15,15 +15,15 @@
-
+
Offline
-
+
- - {{ selectedProfile.metadata.name }} + + {{ selectedProcess.profile.name }}
- @@ -93,7 +98,7 @@ v-tooltip="'View logs'" icon-only class="icon-button" - @click.stop="goToTerminal(profile.path)" + @click.stop="goToTerminal(process.profile.path)" > @@ -106,19 +111,15 @@ import { DownloadIcon, StopCircleIcon, TerminalSquareIcon, DropdownIcon } from '@modrinth/assets' import { Button, Card } from '@modrinth/ui' import { onBeforeUnmount, onMounted, ref } from 'vue' -import { - get_all_running_profiles as getRunningProfiles, - kill_by_uuid as killProfile, - get_uuids_by_profile_path as getProfileProcesses, -} from '@/helpers/process' -import { loading_listener, process_listener, offline_listener } from '@/helpers/events' +import { get_all as getRunningProcesses, kill as killProcess } from '@/helpers/process' +import { loading_listener, process_listener } from '@/helpers/events' import { useRouter } from 'vue-router' import { progress_bars_list } from '@/helpers/state.js' -import { refreshOffline, isOffline } from '@/helpers/utils.js' import ProgressBar from '@/components/ui/ProgressBar.vue' import { handleError } from '@/store/notifications.js' import { mixpanel_track } from '@/helpers/mixpanel' import { ChatIcon } from '@/assets/icons' +import { get_many } from '@/helpers/profile.js' const router = useRouter() const card = ref(null) @@ -129,38 +130,44 @@ const showCard = ref(false) const showProfiles = ref(false) -const currentProcesses = ref(await getRunningProfiles().catch(handleError)) -const selectedProfile = ref(currentProcesses.value[0]) +const currentProcesses = ref([]) +const selectedProcess = ref() -const offline = ref(await isOffline().catch(handleError)) -const refreshInternet = async () => { - offline.value = await refreshOffline().catch(handleError) +const refresh = async () => { + const processes = await getRunningProcesses().catch(handleError) + const profiles = await get_many(processes.map((x) => x.profile_path)).catch(handleError) + + currentProcesses.value = processes.map((x) => ({ + profile: profiles.find((prof) => x.profile_path === prof.path), + ...x, + })) + if (!selectedProcess.value || !currentProcesses.value.includes(selectedProcess.value)) { + selectedProcess.value = currentProcesses.value[0] + } } +await refresh() + +const offline = ref(!navigator.onLine) +window.addEventListener('offline', () => { + offline.value = true +}) +window.addEventListener('online', () => { + offline.value = false +}) + const unlistenProcess = await process_listener(async () => { await refresh() }) -const unlistenRefresh = await offline_listener(async (b) => { - offline.value = b - await refresh() -}) - -const refresh = async () => { - currentProcesses.value = await getRunningProfiles().catch(handleError) - if (!currentProcesses.value.includes(selectedProfile.value)) { - selectedProfile.value = currentProcesses.value[0] - } -} - -const stop = async (path) => { +const stop = async (process) => { try { - const processes = await getProfileProcesses(path ?? selectedProfile.value.path) - await killProfile(processes[0]) + console.log(process.pid) + await killProcess(process.pid).catch(handleError) mixpanel_track('InstanceStop', { - loader: currentProcesses.value[0].metadata.loader, - game_version: currentProcesses.value[0].metadata.game_version, + loader: process.profile.loader, + game_version: process.profile.game_version, source: 'AppBar', }) } catch (e) { @@ -170,7 +177,7 @@ const stop = async (path) => { } const goToTerminal = (path) => { - router.push(`/instance/${encodeURIComponent(path ?? selectedProfile.value.path)}/logs`) + router.push(`/instance/${encodeURIComponent(path ?? selectedProcess.value.profile.path)}/logs`) } const currentLoadingBars = ref([]) @@ -182,8 +189,8 @@ const refreshInfo = async () => { if (x.bar_type.type === 'java_download') { x.title = 'Downloading Java ' + x.bar_type.version } - if (x.bar_type.profile_name) { - x.title = x.bar_type.profile_name + if (x.bar_type.profile_path) { + x.title = x.bar_type.profile_path } if (x.bar_type.pack_name) { x.title = x.bar_type.pack_name @@ -215,8 +222,8 @@ const unlistenLoading = await loading_listener(async () => { await refreshInfo() }) -const selectProfile = (profile) => { - selectedProfile.value = profile +const selectProcess = (process) => { + selectedProcess.value = process showProfiles.value = false } @@ -267,7 +274,6 @@ onBeforeUnmount(() => { window.removeEventListener('click', handleClickOutsideProfile) unlistenProcess() unlistenLoading() - unlistenRefresh() }) diff --git a/apps/app-frontend/src/components/ui/SearchCard.vue b/apps/app-frontend/src/components/ui/SearchCard.vue index 6b8e9bee..4c17ca5c 100644 --- a/apps/app-frontend/src/components/ui/SearchCard.vue +++ b/apps/app-frontend/src/components/ui/SearchCard.vue @@ -69,12 +69,7 @@ import { formatNumber, formatCategory } from '@modrinth/utils' import dayjs from 'dayjs' import relativeTime from 'dayjs/plugin/relativeTime' import { ref } from 'vue' -import { add_project_from_version as installMod, list } from '@/helpers/profile.js' -import { install as packInstall } from '@/helpers/pack.js' -import { installVersionDependencies } from '@/helpers/utils.js' -import { useFetch } from '@/helpers/fetch.js' -import { handleError } from '@/store/notifications.js' -import { mixpanel_track } from '@/helpers/mixpanel' +import { install as installVersion } from '@/store/install.js' dayjs.extend(relativeTime) const props = defineProps({ @@ -94,18 +89,6 @@ const props = defineProps({ type: Object, default: null, }, - confirmModal: { - type: Object, - default: null, - }, - modInstallModal: { - type: Object, - default: null, - }, - incompatibilityWarningModal: { - type: Object, - default: null, - }, featured: { type: Boolean, default: false, @@ -123,93 +106,19 @@ const installed = ref(props.installed) async function install() { installing.value = true - const versions = await useFetch( - `https://api.modrinth.com/v2/project/${props.project.project_id}/version`, - 'project versions', - ) - let queuedVersionData - - if (!props.instance) { - queuedVersionData = versions[0] - } else { - queuedVersionData = versions.find( - (v) => - v.game_versions.includes(props.instance.metadata.game_version) && - (props.project.project_type !== 'mod' || - v.loaders.includes(props.instance.metadata.loader)), - ) - } - - if (props.project.project_type === 'modpack') { - const packs = Object.values(await list().catch(handleError)) - if ( - packs.length === 0 || - !packs - .map((value) => value.metadata) - .find((pack) => pack.linked_data?.project_id === props.project.project_id) - ) { - await packInstall( - props.project.project_id, - queuedVersionData.id, - props.project.title, - props.project.icon_url, - ).catch(handleError) - - mixpanel_track('PackInstall', { - id: props.project.project_id, - version_id: queuedVersionData.id, - title: props.project.title, - source: 'SearchCard', - }) - } else { - props.confirmModal.show( - props.project.project_id, - queuedVersionData.id, - props.project.title, - props.project.icon_url, - ) - } - } else { - if (props.instance) { - if (!queuedVersionData) { - props.incompatibilityWarningModal.show( - props.instance, - props.project.title, - versions, - () => (installed.value = true), - props.project.project_id, - props.project.project_type, - ) - installing.value = false - return - } else { - await installMod(props.instance.path, queuedVersionData.id).catch(handleError) - await installVersionDependencies(props.instance, queuedVersionData) - - mixpanel_track('ProjectInstall', { - loader: props.instance.metadata.loader, - game_version: props.instance.metadata.game_version, - id: props.project.project_id, - project_type: props.project.project_type, - version_id: queuedVersionData.id, - title: props.project.title, - source: 'SearchCard', - }) - } - } else { - props.modInstallModal.show( - props.project.project_id, - versions, - props.project.title, - props.project.project_type, - ) + await installVersion( + props.project.project_id, + null, + props.instance ? props.instance.path : null, + 'SearchCard', + (version) => { installing.value = false - return - } - if (props.instance) installed.value = true - } - installing.value = false + if (props.instance && version) { + installed.value = true + } + }, + ) } diff --git a/apps/app-frontend/src/components/ui/URLConfirmModal.vue b/apps/app-frontend/src/components/ui/URLConfirmModal.vue index c3d8fad8..7d47d9d1 100644 --- a/apps/app-frontend/src/components/ui/URLConfirmModal.vue +++ b/apps/app-frontend/src/components/ui/URLConfirmModal.vue @@ -1,77 +1,37 @@ @@ -96,7 +56,6 @@ async function install() {
- diff --git a/apps/app-frontend/src/components/ui/tutorial/OnboardingScreen.vue b/apps/app-frontend/src/components/ui/tutorial/OnboardingScreen.vue index ab71c108..ae694c40 100644 --- a/apps/app-frontend/src/components/ui/tutorial/OnboardingScreen.vue +++ b/apps/app-frontend/src/components/ui/tutorial/OnboardingScreen.vue @@ -34,7 +34,7 @@ const prevPage = () => { const finishOnboarding = async () => { mixpanel.track('OnboardingFinish') const settings = await get() - settings.fully_onboarded = true + settings.onboarded = true await set(settings) props.finish() } diff --git a/apps/app-frontend/src/helpers/auth.js b/apps/app-frontend/src/helpers/auth.js index cf228c8d..976c8b0a 100644 --- a/apps/app-frontend/src/helpers/auth.js +++ b/apps/app-frontend/src/helpers/auth.js @@ -45,11 +45,3 @@ export async function remove_user(user) { export async function users() { return await invoke('plugin:auth|auth_users') } - -// Get a user by UUID -// Prefer to use refresh() instead of this because it will refresh the credentials -// user is UUID -// Returns Credentials (of user) -export async function get_user(user) { - return await invoke('plugin:auth|auth_get_user', { user }) -} diff --git a/apps/app-frontend/src/helpers/cache.js b/apps/app-frontend/src/helpers/cache.js new file mode 100644 index 00000000..c64ff440 --- /dev/null +++ b/apps/app-frontend/src/helpers/cache.js @@ -0,0 +1,49 @@ +import { invoke } from '@tauri-apps/api/tauri' + +export async function get_project(id) { + return await invoke('plugin:cache|get_project', { id }) +} + +export async function get_project_many(ids) { + return await invoke('plugin:cache|get_project_many', { ids }) +} + +export async function get_version(id) { + return await invoke('plugin:cache|get_version', { id }) +} + +export async function get_version_many(ids) { + return await invoke('plugin:cache|get_version_many', { ids }) +} + +export async function get_user(id) { + return await invoke('plugin:cache|get_user', { id }) +} + +export async function get_user_many(ids) { + return await invoke('plugin:cache|get_user_many', { ids }) +} + +export async function get_team(id) { + return await invoke('plugin:cache|get_team', { id }) +} + +export async function get_team_many(ids) { + return await invoke('plugin:cache|get_team_many', { ids }) +} + +export async function get_organization(id) { + return await invoke('plugin:cache|get_organization', { id }) +} + +export async function get_organization_many(ids) { + return await invoke('plugin:cache|get_organization_many', { ids }) +} + +export async function get_search_results(id) { + return await invoke('plugin:cache|get_search_results', { id }) +} + +export async function get_search_results_many(ids) { + return await invoke('plugin:cache|get_search_results_many', { ids }) +} diff --git a/apps/app-frontend/src/helpers/events.js b/apps/app-frontend/src/helpers/events.js index d8899a78..3bc07bcb 100644 --- a/apps/app-frontend/src/helpers/events.js +++ b/apps/app-frontend/src/helpers/events.js @@ -17,7 +17,7 @@ // event.payload is the payload object console.log(event) }) - + Putting that in a script will print any emitted signal from rust */ import { listen } from '@tauri-apps/api/event' @@ -93,15 +93,3 @@ export async function command_listener(callback) { export async function warning_listener(callback) { return await listen('warning', (event) => callback(event.payload)) } - -/// Payload for the 'offline' event -/* - OfflinePayload { - offline: bool, true or false - } -*/ -export async function offline_listener(callback) { - return await listen('offline', (event) => { - return callback(event.payload) - }) -} diff --git a/apps/app-frontend/src/helpers/jre.js b/apps/app-frontend/src/helpers/jre.js index 57158844..7ad4a42c 100644 --- a/apps/app-frontend/src/helpers/jre.js +++ b/apps/app-frontend/src/helpers/jre.js @@ -14,6 +14,14 @@ JavaVersion { */ +export async function get_java_versions() { + return await invoke('plugin:jre|get_java_versions') +} + +export async function set_java_version(javaVersion) { + return await invoke('plugin:jre|set_java_version', { javaVersion }) +} + // Finds all the installation of Java 7, if it exists // Returns [JavaVersion] export async function find_filtered_jres(version) { diff --git a/apps/app-frontend/src/helpers/metadata.js b/apps/app-frontend/src/helpers/metadata.js index ae64baa5..6f2c15be 100644 --- a/apps/app-frontend/src/helpers/metadata.js +++ b/apps/app-frontend/src/helpers/metadata.js @@ -6,34 +6,8 @@ export async function get_game_versions() { return await invoke('plugin:metadata|metadata_get_game_versions') } -// Gets the fabric versions from daedalus +// Gets the given loader versions from daedalus // Returns Manifest -export async function get_fabric_versions() { - const c = await invoke('plugin:metadata|metadata_get_fabric_versions') - console.log('Getting fabric versions', c) - return c -} - -// Gets the forge versions from daedalus -// Returns Manifest -export async function get_forge_versions() { - const c = await invoke('plugin:metadata|metadata_get_forge_versions') - console.log('Getting forge versions', c) - return c -} - -// Gets the quilt versions from daedalus -// Returns Manifest -export async function get_quilt_versions() { - const c = await invoke('plugin:metadata|metadata_get_quilt_versions') - console.log('Getting quilt versions', c) - return c -} - -// Gets the neoforge versions from daedalus -// Returns Manifest -export async function get_neoforge_versions() { - const c = await invoke('plugin:metadata|metadata_get_neoforge_versions') - console.log('Getting neoforge versions', c) - return c +export async function get_loader_versions(loader) { + return await invoke('plugin:metadata|metadata_get_loader_versions', { loader }) } diff --git a/apps/app-frontend/src/helpers/mr_auth.js b/apps/app-frontend/src/helpers/mr_auth.js index 889faffd..ae0e1961 100644 --- a/apps/app-frontend/src/helpers/mr_auth.js +++ b/apps/app-frontend/src/helpers/mr_auth.js @@ -5,17 +5,10 @@ */ import { invoke } from '@tauri-apps/api/tauri' -export async function authenticate_begin_flow(provider) { - return await invoke('plugin:mr_auth|authenticate_begin_flow', { provider }) +export async function login(provider) { + return await invoke('modrinth_auth_login', { provider }) } -export async function authenticate_await_completion() { - return await invoke('plugin:mr_auth|authenticate_await_completion') -} - -export async function cancel_flow() { - return await invoke('plugin:mr_auth|cancel_flow') -} export async function login_pass(username, password, challenge) { return await invoke('plugin:mr_auth|login_pass', { username, password, challenge }) } @@ -34,10 +27,6 @@ export async function create_account(username, email, password, challenge, signU }) } -export async function refresh() { - return await invoke('plugin:mr_auth|refresh') -} - export async function logout() { return await invoke('plugin:mr_auth|logout') } diff --git a/apps/app-frontend/src/helpers/pack.js b/apps/app-frontend/src/helpers/pack.js index a6f3f06c..d1ae241d 100644 --- a/apps/app-frontend/src/helpers/pack.js +++ b/apps/app-frontend/src/helpers/pack.js @@ -21,7 +21,8 @@ export async function install(projectId, versionId, packTitle, iconUrl) { profile_creator.gameVersion, profile_creator.modloader, profile_creator.loaderVersion, - profile_creator.icon, + null, + true, ) return await invoke('plugin:pack|pack_install', { location, profile }) @@ -39,7 +40,8 @@ export async function install_from_file(path) { profile_creator.gameVersion, profile_creator.modloader, profile_creator.loaderVersion, - profile_creator.icon, + null, + true, ) return await invoke('plugin:pack|pack_install', { location, profile }) } diff --git a/apps/app-frontend/src/helpers/process.js b/apps/app-frontend/src/helpers/process.js index 3a048ba6..94df7f8f 100644 --- a/apps/app-frontend/src/helpers/process.js +++ b/apps/app-frontend/src/helpers/process.js @@ -5,49 +5,19 @@ */ import { invoke } from '@tauri-apps/api/tauri' -/// Gets if a process has finished by UUID -/// Returns bool -export async function has_finished_by_uuid(uuid) { - return await invoke('plugin:process|process_has_finished_by_uuid', { uuid }) -} - -/// Gets process exit status by UUID -/// Returns u32 -export async function get_exit_status_by_uuid(uuid) { - return await invoke('plugin:process|process_get_exit_status_by_uuid', { uuid }) -} - -/// Gets all process IDs +/// Gets all running process IDs with a given profile path /// Returns [u32] -export async function get_all_uuids() { - return await invoke('plugin:process|process_get_all_uuids') -} - -/// Gets all running process IDs -/// Returns [u32] -export async function get_all_running_uuids() { - return await invoke('plugin:process|process_get_all_running_uuids') +export async function get_by_profile_path(path) { + return await invoke('plugin:process|process_get_by_profile_path', { path }) } /// Gets all running process IDs with a given profile path /// Returns [u32] -export async function get_uuids_by_profile_path(profilePath) { - return await invoke('plugin:process|process_get_uuids_by_profile_path', { profilePath }) -} - -/// Gets all running process IDs with a given profile path -/// Returns [u32] -export async function get_all_running_profile_paths(profilePath) { - return await invoke('plugin:process|process_get_all_running_profile_paths', { profilePath }) -} - -/// Gets all running process IDs with a given profile path -/// Returns [u32] -export async function get_all_running_profiles() { - return await invoke('plugin:process|process_get_all_running_profiles') +export async function get_all() { + return await invoke('plugin:process|process_get_all') } /// Kills a process by UUID -export async function kill_by_uuid(uuid) { - return await invoke('plugin:process|process_kill_by_uuid', { uuid }) +export async function kill(pid) { + return await invoke('plugin:process|process_kill', { pid }) } diff --git a/apps/app-frontend/src/helpers/profile.js b/apps/app-frontend/src/helpers/profile.js index b709f2ed..2e6ac703 100644 --- a/apps/app-frontend/src/helpers/profile.js +++ b/apps/app-frontend/src/helpers/profile.js @@ -16,7 +16,7 @@ import { invoke } from '@tauri-apps/api/tauri' - icon is a path to an image file, which will be copied into the profile directory */ -export async function create(name, gameVersion, modloader, loaderVersion, icon, noWatch) { +export async function create(name, gameVersion, modloader, loaderVersion, iconPath, skipInstall) { //Trim string name to avoid "Unable to find directory" name = name.trim() return await invoke('plugin:profile_create|profile_create', { @@ -24,8 +24,8 @@ export async function create(name, gameVersion, modloader, loaderVersion, icon, gameVersion, modloader, loaderVersion, - icon, - noWatch, + iconPath, + skipInstall, }) } @@ -41,8 +41,18 @@ export async function remove(path) { // Get a profile by path // Returns a Profile -export async function get(path, clearProjects) { - return await invoke('plugin:profile|profile_get', { path, clearProjects }) +export async function get(path) { + return await invoke('plugin:profile|profile_get', { path }) +} + +export async function get_many(paths) { + return await invoke('plugin:profile|profile_get_many', { paths }) +} + +// Get a profile's projects +// Returns a map of a path to profile file +export async function get_projects(path) { + return await invoke('plugin:profile|profile_get_projects', { path }) } // Get a profile's full fs path @@ -65,8 +75,8 @@ export async function get_optimal_jre_key(path) { // Get a copy of the profile set // Returns hashmap of path -> Profile -export async function list(clearProjects) { - return await invoke('plugin:profile|profile_list', { clearProjects }) +export async function list() { + return await invoke('plugin:profile|profile_list') } export async function check_installed(path, projectId) { @@ -163,10 +173,8 @@ export async function run(path) { return await invoke('plugin:profile|profile_run', { path }) } -// Run Minecraft using a pathed profile -// Waits for end -export async function run_wait(path) { - return await invoke('plugin:profile|profile_run_wait', { path }) +export async function kill(path) { + return await invoke('plugin:profile|profile_kill', { path }) } // Edits a profile diff --git a/apps/app-frontend/src/helpers/state.js b/apps/app-frontend/src/helpers/state.js index 9a246f0b..d2867185 100644 --- a/apps/app-frontend/src/helpers/state.js +++ b/apps/app-frontend/src/helpers/state.js @@ -16,11 +16,6 @@ export async function progress_bars_list() { return await invoke('plugin:utils|progress_bars_list') } -// Check if any safe loading bars are active -export async function check_safe_loading_bars_complete() { - return await invoke('plugin:utils|safety_check_safe_loading_bars') -} - // Get opening command // For example, if a user clicks on an .mrpack to open the app. // This should be called once and only when the app is done booting up and ready to receive a command @@ -28,8 +23,3 @@ export async function check_safe_loading_bars_complete() { export async function get_opening_command() { return await invoke('plugin:utils|get_opening_command') } - -// Wait for settings to sync -export async function await_sync() { - return await invoke('plugin:utils|await_sync') -} diff --git a/apps/app-frontend/src/helpers/tags.js b/apps/app-frontend/src/helpers/tags.js index aa9955c4..11f502aa 100644 --- a/apps/app-frontend/src/helpers/tags.js +++ b/apps/app-frontend/src/helpers/tags.js @@ -5,11 +5,6 @@ */ import { invoke } from '@tauri-apps/api/tauri' -// Gets tag bundle of all tags -export async function get_tag_bundle() { - return await invoke('plugin:tags|tags_get_tag_bundle') -} - // Gets cached category tags export async function get_categories() { return await invoke('plugin:tags|tags_get_categories') diff --git a/apps/app-frontend/src/helpers/utils.js b/apps/app-frontend/src/helpers/utils.js index 08d63bc0..d63adbe8 100644 --- a/apps/app-frontend/src/helpers/utils.js +++ b/apps/app-frontend/src/helpers/utils.js @@ -1,11 +1,4 @@ -import { - add_project_from_version as installMod, - check_installed, - get_full_path, - get_mod_full_path, -} from '@/helpers/profile' -import { useFetch } from '@/helpers/fetch.js' -import { handleError } from '@/store/notifications.js' +import { get_full_path, get_mod_full_path } from '@/helpers/profile' import { invoke } from '@tauri-apps/api/tauri' export async function isDev() { @@ -49,55 +42,16 @@ export const releaseColor = (releaseType) => { } } -export const installVersionDependencies = async (profile, version) => { - for (const dep of version.dependencies) { - if (dep.dependency_type !== 'required') continue - // disallow fabric api install on quilt - if (dep.project_id === 'P7dR8mSH' && profile.metadata.loader === 'quilt') continue - if (dep.version_id) { - if ( - dep.project_id && - (await check_installed(profile.path, dep.project_id).catch(handleError)) - ) - continue - await installMod(profile.path, dep.version_id) - } else { - if ( - dep.project_id && - (await check_installed(profile.path, dep.project_id).catch(handleError)) - ) - continue - const depVersions = await useFetch( - `https://api.modrinth.com/v2/project/${dep.project_id}/version`, - 'dependency versions', - ) - const latest = depVersions.find( - (v) => - v.game_versions.includes(profile.metadata.game_version) && - v.loaders.includes(profile.metadata.loader), - ) - if (latest) { - await installMod(profile.path, latest.id).catch(handleError) - } +export function debounce(fn, wait) { + let timer + return function (...args) { + if (timer) { + clearTimeout(timer) // clear any pre-existing timer } + // eslint-disable-next-line @typescript-eslint/no-this-alias + const context = this // get the current context + timer = setTimeout(() => { + fn.apply(context, args) // call the function if time expires + }, wait) } } - -export const openLink = (url) => { - window.__TAURI_INVOKE__('tauri', { - __tauriModule: 'Shell', - message: { - cmd: 'open', - path: url, - }, - }) -} - -export const refreshOffline = async () => { - return await invoke('plugin:utils|refresh_offline', {}) -} - -// returns true/false -export const isOffline = async () => { - return await invoke('plugin:utils|is_offline', {}) -} diff --git a/apps/app-frontend/src/pages/Browse.vue b/apps/app-frontend/src/pages/Browse.vue index 57121fe2..f1463e03 100644 --- a/apps/app-frontend/src/pages/Browse.vue +++ b/apps/app-frontend/src/pages/Browse.vue @@ -10,6 +10,7 @@ import { NavRow, Card, SearchFilter, + Avatar, } from '@modrinth/ui' import { formatCategoryHeader, formatCategory } from '@modrinth/utils' import Multiselect from 'vue-multiselect' @@ -17,29 +18,22 @@ import { handleError } from '@/store/state' import { useBreadcrumbs } from '@/store/breadcrumbs' import { get_categories, get_loaders, get_game_versions } from '@/helpers/tags' import { useRoute, useRouter } from 'vue-router' -import { Avatar } from '@modrinth/ui' import SearchCard from '@/components/ui/SearchCard.vue' -import InstallConfirmModal from '@/components/ui/InstallConfirmModal.vue' -import ModInstallModal from '@/components/ui/ModInstallModal.vue' import SplashScreen from '@/components/ui/SplashScreen.vue' -import IncompatibilityWarningModal from '@/components/ui/IncompatibilityWarningModal.vue' -import { useFetch } from '@/helpers/fetch.js' -import { check_installed, get, get as getInstance } from '@/helpers/profile.js' +import { get as getInstance, get_projects as getInstanceProjects } from '@/helpers/profile.js' import { convertFileSrc } from '@tauri-apps/api/tauri' -import { isOffline } from '@/helpers/utils' -import { offline_listener } from '@/helpers/events' - +import { get_search_results } from '@/helpers/cache.js' +import { debounce } from '@/helpers/utils.js' const router = useRouter() const route = useRoute() -const offline = ref(await isOffline()) -const unlistenOffline = await offline_listener((b) => { - offline.value = b +const offline = ref(!navigator.onLine) +window.addEventListener('offline', () => { + offline.value = true +}) +window.addEventListener('online', () => { + offline.value = false }) - -const confirmModal = ref(null) -const modInstallModal = ref(null) -const incompatibilityWarningModal = ref(null) const breadcrumbs = useBreadcrumbs() breadcrumbs.setContext({ name: 'Browse', link: route.path, query: route.query }) @@ -65,6 +59,7 @@ const maxResults = ref(20) const currentPage = ref(1) const projectType = ref(route.params.projectType) const instanceContext = ref(null) +const instanceProjects = ref(null) const ignoreInstanceLoaders = ref(false) const ignoreInstanceGameVersions = ref(false) @@ -88,7 +83,10 @@ if (route.query.il) { ignoreInstanceLoaders.value = route.query.il === 'true' } if (route.query.i) { - instanceContext.value = await getInstance(route.query.i, true) + ;[instanceContext.value, instanceProjects.value] = await Promise.all([ + getInstance(route.query.i).catch(handleError), + getInstanceProjects(route.query.i).catch(handleError), + ]) } if (route.query.q) { query.value = route.query.q @@ -144,18 +142,16 @@ if (route.query.ai) { } async function refreshSearch() { - const base = 'https://api.modrinth.com/v2/' - const params = [`limit=${maxResults.value}`, `index=${sortType.value.name}`] if (query.value.length > 0) { params.push(`query=${query.value.replace(/ /g, '+')}`) } if (instanceContext.value) { if (!ignoreInstanceLoaders.value && projectType.value === 'mod') { - orFacets.value = [`categories:${encodeURIComponent(instanceContext.value.metadata.loader)}`] + orFacets.value = [`categories:${encodeURIComponent(instanceContext.value.loader)}`] } if (!ignoreInstanceGameVersions.value) { - selectedVersions.value = [instanceContext.value.metadata.game_version] + selectedVersions.value = [instanceContext.value.game_version] } } if ( @@ -224,13 +220,11 @@ async function refreshSearch() { } if (hideAlreadyInstalled.value) { - const installedMods = await get(instanceContext.value.path, false).then((x) => - Object.values(x.projects) - .filter((x) => x.metadata.project) - .map((x) => x.metadata.project.id), - ) + const installedMods = Object.values(instanceProjects.value) + .filter((x) => x.metadata) + .map((x) => x.metadata.project_id) + installedMods.map((x) => [`project_id != ${x}`]).forEach((x) => formattedFacets.push(x)) - console.log(`facets=${JSON.stringify(formattedFacets)}`) } params.push(`facets=${JSON.stringify(formattedFacets)}`) @@ -246,24 +240,24 @@ async function refreshSearch() { } } - let val = `${base}${url}` - - let rawResults = await useFetch(val, 'search results', offline.value) + let rawResults = await get_search_results(`?${url}`) if (!rawResults) { rawResults = { - hits: [], - total_hits: 0, - limit: 1, + result: { + hits: [], + total_hits: 0, + limit: 1, + }, } } if (instanceContext.value) { - for (val of rawResults.hits) { - val.installed = await check_installed(instanceContext.value.path, val.project_id).then( - (x) => (val.installed = x), + for (const val of rawResults.result.hits) { + val.installed = Object.values(instanceProjects.value).some( + (x) => x.metadata && x.metadata.project_id === val.project_id, ) } } - results.value = rawResults + results.value = rawResults.result } async function onSearchChange(newPageNumber) { @@ -282,6 +276,8 @@ async function onSearchChange(newPageNumber) { } } +const debouncedSearchChange = debounce(() => onSearchChange(1), 200) + const searchWrapper = ref(null) async function onSearchChangeToTop(newPageNumber) { await onSearchChange(newPageNumber) @@ -505,13 +501,13 @@ const selectableProjectTypes = computed(() => { if (instanceContext.value) { if ( availableGameVersions.value.findIndex( - (x) => x.version === instanceContext.value.metadata.game_version, + (x) => x.version === instanceContext.value.game_version, ) <= availableGameVersions.value.findIndex((x) => x.version === '1.13') ) { values.unshift({ label: 'Data Packs', href: `/browse/datapack` }) } - if (instanceContext.value.metadata.loader !== 'vanilla') { + if (instanceContext.value.loader !== 'vanilla') { values.unshift({ label: 'Mods', href: '/browse/mod' }) } } else { @@ -528,8 +524,6 @@ const showVersions = computed( ) const isModProject = computed(() => ['modpack', 'mod'].includes(projectType.value)) - -onUnmounted(() => unlistenOffline()) diff --git a/apps/app-frontend/src/pages/Index.vue b/apps/app-frontend/src/pages/Index.vue index 521bcf5a..1d51e2f2 100644 --- a/apps/app-frontend/src/pages/Index.vue +++ b/apps/app-frontend/src/pages/Index.vue @@ -1,14 +1,13 @@ @@ -105,6 +107,7 @@ onUnmounted(() => { label: 'Jump back in', route: '/library', instances: recentInstances, + instance: true, downloaded: true, }, { diff --git a/apps/app-frontend/src/pages/Library.vue b/apps/app-frontend/src/pages/Library.vue index e10a521b..03b8970a 100644 --- a/apps/app-frontend/src/pages/Library.vue +++ b/apps/app-frontend/src/pages/Library.vue @@ -4,34 +4,33 @@ import GridDisplay from '@/components/GridDisplay.vue' import { list } from '@/helpers/profile.js' import { useRoute } from 'vue-router' import { useBreadcrumbs } from '@/store/breadcrumbs' -import { offline_listener, profile_listener } from '@/helpers/events.js' +import { profile_listener } from '@/helpers/events.js' import { handleError } from '@/store/notifications.js' import { Button } from '@modrinth/ui' import { PlusIcon } from '@modrinth/assets' import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue' import { NewInstanceImage } from '@/assets/icons' -import { isOffline } from '@/helpers/utils' const route = useRoute() const breadcrumbs = useBreadcrumbs() breadcrumbs.setRootContext({ name: 'Library', link: route.path }) -const profiles = await list(true).catch(handleError) -const instances = shallowRef(Object.values(profiles)) +const instances = shallowRef(await list().catch(handleError)) -const offline = ref(await isOffline()) -const unlistenOffline = await offline_listener((b) => { - offline.value = b +const offline = ref(!navigator.onLine) +window.addEventListener('offline', () => { + offline.value = true +}) +window.addEventListener('online', () => { + offline.value = false }) const unlistenProfile = await profile_listener(async () => { - const profiles = await list(true).catch(handleError) - instances.value = Object.values(profiles) + instances.value = await list().catch(handleError) }) onUnmounted(() => { unlistenProfile() - unlistenOffline() }) diff --git a/apps/app-frontend/src/pages/Settings.vue b/apps/app-frontend/src/pages/Settings.vue index 8d576b68..d1ee7606 100644 --- a/apps/app-frontend/src/pages/Settings.vue +++ b/apps/app-frontend/src/pages/Settings.vue @@ -4,7 +4,7 @@ import { LogOutIcon, LogInIcon, BoxIcon, FolderSearchIcon, UpdatedIcon } from '@ import { Card, Slider, DropdownSelect, Toggle, Modal, Button } from '@modrinth/ui' import { handleError, useTheming } from '@/store/state' import { is_dir_writeable, change_config_dir, get, set } from '@/helpers/settings' -import { get_max_memory } from '@/helpers/jre' +import { get_java_versions, get_max_memory, set_java_version } from '@/helpers/jre' import { get as getCreds, logout } from '@/helpers/mr_auth.js' import JavaSelector from '@/components/ui/JavaSelector.vue' import ModrinthLoginScreen from '@/components/ui/tutorial/ModrinthLoginScreen.vue' @@ -12,6 +12,7 @@ import { mixpanel_opt_out_tracking, mixpanel_opt_in_tracking } from '@/helpers/m import { open } from '@tauri-apps/api/dialog' import { getOS } from '@/helpers/utils.js' import { getVersion } from '@tauri-apps/api/app' +import { get_user } from '@/helpers/cache.js' const pageOptions = ['Home', 'Library'] @@ -22,8 +23,8 @@ const version = await getVersion() const accessSettings = async () => { const settings = await get() - settings.javaArgs = settings.custom_java_args.join(' ') - settings.envArgs = settings.custom_env_args.map((x) => x.join('=')).join(' ') + settings.launchArgs = settings.extra_launch_args.join(' ') + settings.envVars = settings.custom_env_vars.map((x) => x.join('=')).join(' ') return settings } @@ -31,7 +32,8 @@ const accessSettings = async () => { const fetchSettings = await accessSettings().catch(handleError) const settings = ref(fetchSettings) -const settingsDir = ref(settings.value.loaded_config_dir) +// const settingsDir = ref(settings.value.loaded_config_dir) + const maxMemory = ref(Math.floor((await get_max_memory().catch(handleError)) / 1024)) watch( @@ -43,26 +45,14 @@ watch( const setSettings = JSON.parse(JSON.stringify(newSettings)) - if (setSettings.opt_out_analytics) { + if (setSettings.telemetry) { mixpanel_opt_out_tracking() } else { mixpanel_opt_in_tracking() } - for (const [key, value] of Object.entries(setSettings.java_globals)) { - if (value?.path === '') { - value.path = undefined - } - - if (value?.path) { - value.path = value.path.replace('java.exe', 'javaw.exe') - } - - console.log(`${key}: ${value}`) - } - - setSettings.custom_java_args = setSettings.javaArgs.trim().split(/\s+/).filter(Boolean) - setSettings.custom_env_args = setSettings.envArgs + setSettings.extra_launch_args = setSettings.launchArgs.trim().split(/\s+/).filter(Boolean) + setSettings.custom_env_vars = setSettings.envVars .trim() .split(/\s+/) .filter(Boolean) @@ -78,22 +68,49 @@ watch( setSettings.hooks.post_exit = null } + if (!setSettings.custom_dir) { + setSettings.custom_dir = null + } + await set(setSettings) }, { deep: true }, ) -const credentials = ref(await getCreds().catch(handleError)) +const javaVersions = ref(await get_java_versions().catch(handleError)) +async function updateJavaVersion(version) { + if (version?.path === '') { + version.path = undefined + } + + if (version?.path) { + version.path = version.path.replace('java.exe', 'javaw.exe') + } + + await set_java_version(version).catch(handleError) +} + +async function fetchCredentials() { + const creds = await getCreds().catch(handleError) + console.log(creds) + if (creds && creds.user_id) { + creds.user = await get_user(creds.user_id).catch(handleError) + } + credentials.value = creds +} + +const credentials = ref() +await fetchCredentials() + const loginScreenModal = ref() async function logOut() { await logout().catch(handleError) - credentials.value = await getCreds().catch(handleError) + await fetchCredentials() } async function signInAfter() { - loginScreenModal.value.hide() - credentials.value = await getCreds().catch(handleError) + await fetchCredentials() } async function findLauncherDir() { @@ -103,24 +120,10 @@ async function findLauncherDir() { title: 'Select a new app directory', }) - const writeable = await is_dir_writeable(newDir) - - if (!writeable) { - handleError('The selected directory does not have proper permissions for write access.') - return - } - if (newDir) { - settingsDir.value = newDir - await refreshDir() + settings.value.custom_dir = newDir } } - -async function refreshDir() { - await change_config_dir(settingsDir.value).catch(handleError) - settings.value = await accessSettings().catch(handleError) - settingsDir.value = settings.value.loaded_config_dir -}