diff --git a/.env.template b/.env.template new file mode 100644 index 00000000..1be53bd6 --- /dev/null +++ b/.env.template @@ -0,0 +1 @@ +DATABASE_URL=sqlite://path/to/user_data.db diff --git a/Cargo.lock b/Cargo.lock index 890a6c8a..19cb4927 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,34 +17,12 @@ dependencies = [ "gimli", ] -[[package]] -name = "adler" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" - [[package]] name = "adler2" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" -[[package]] -name = "adler32" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aae1277d39aeec15cb388266ecc24b11c80469deae6067e17a1a7aa9e5c1f234" - -[[package]] -name = "aead" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" -dependencies = [ - "crypto-common", - "generic-array", -] - [[package]] name = "aes" version = "0.8.4" @@ -56,30 +34,15 @@ dependencies = [ "cpufeatures", ] -[[package]] -name = "aes-gcm" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "831010a0f742e1209b3bcea8fab6a8e149051ba6099432c8cb2cc117dec3ead1" -dependencies = [ - "aead", - "aes", - "cipher", - "ctr", - "ghash", - "subtle", -] - [[package]] name = "ahash" -version = "0.8.11" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" dependencies = [ - "cfg-if", + "getrandom 0.2.15", "once_cell", "version_check", - "zerocopy", ] [[package]] @@ -92,10 +55,10 @@ dependencies = [ ] [[package]] -name = "aligned-vec" -version = "0.5.0" +name = "aliasable" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" +checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" [[package]] name = "alloc-no-stdlib" @@ -133,6 +96,55 @@ dependencies = [ "libc", ] +[[package]] +name = "anstream" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" + +[[package]] +name = "anstyle-parse" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" +dependencies = [ + "anstyle", + "windows-sys 0.59.0", +] + [[package]] name = "anyhow" version = "1.0.89" @@ -148,92 +160,12 @@ dependencies = [ "derive_arbitrary", ] -[[package]] -name = "arboard" -version = "3.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" -dependencies = [ - "clipboard-win", - "core-graphics 0.23.2", - "image", - "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "parking_lot", - "windows-sys 0.48.0", - "x11rb", -] - -[[package]] -name = "arg_enum_proc_macro" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "ashpd" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d43c03d9e36dd40cab48435be0b09646da362c278223ca535493877b2c1dee9" -dependencies = [ - "enumflags2", - "futures-channel", - "futures-util", - "rand 0.8.5", - "raw-window-handle", - "serde", - "serde_repr", - "tokio", - "url", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "zbus", -] - -[[package]] -name = "async-broadcast" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20cd0e2e25ea8e5f7e9df04578dc6cf5c83577fd09b1a46aaf5c85e1c33f2a7e" -dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - -[[package]] -name = "async-channel" -version = "2.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" -dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", -] - [[package]] name = "async-compression" version = "0.4.12" @@ -255,113 +187,27 @@ dependencies = [ ] [[package]] -name = "async-executor" -version = "1.13.1" +name = "async-stream" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30ca9a001c1e8ba5149f91a74362376cc6bc5b919d92d988668657bd570bdcec" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", - "slab", -] - -[[package]] -name = "async-fs" -version = "2.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a" -dependencies = [ - "async-lock", - "blocking", - "futures-lite", -] - -[[package]] -name = "async-io" -version = "2.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "444b0228950ee6501b3568d3c93bf1176a1fdbc3b758dcd9475046d30f4dc7e8" -dependencies = [ - "async-lock", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix", - "slab", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-lock" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff6e472cdea888a4bd64f342f09b3f50e1886d32afe8df3d663c01140b811b18" -dependencies = [ - "event-listener", - "event-listener-strategy", + "async-stream-impl", + "futures-core", "pin-project-lite", ] [[package]] -name = "async-process" -version = "2.3.0" +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63255f1dc2381611000436537bbedfe83183faa303a5a0edaf191edef06526bb" -dependencies = [ - "async-channel", - "async-io", - "async-lock", - "async-signal", - "async-task", - "blocking", - "cfg-if", - "event-listener", - "futures-lite", - "rustix", - "tracing", -] - -[[package]] -name = "async-recursion" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", "syn 2.0.87", ] -[[package]] -name = "async-signal" -version = "0.2.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "637e00349800c0bdf8bfc21ebbc0b6524abea702b0da4168ac00d070d0c0b9f3" -dependencies = [ - "async-io", - "async-lock", - "atomic-waker", - "cfg-if", - "futures-core", - "futures-io", - "rustix", - "signal-hook-registry", - "slab", - "windows-sys 0.59.0", -] - -[[package]] -name = "async-task" -version = "4.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" - [[package]] name = "async-trait" version = "0.1.83" @@ -373,23 +219,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "async-tungstenite" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90e661b6cb0a6eb34d02c520b052daa3aa9ac0cc02495c9d066bbce13ead132b" -dependencies = [ - "futures-io", - "futures-util", - "log", - "pin-project-lite", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tungstenite", - "webpki-roots", -] - [[package]] name = "async_zip" version = "0.0.17" @@ -450,29 +279,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" -[[package]] -name = "av1-grain" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" -dependencies = [ - "anyhow", - "arrayvec", - "log", - "nom", - "num-rational", - "v_frame", -] - -[[package]] -name = "avif-serialize" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" -dependencies = [ - "arrayvec", -] - [[package]] name = "backtrace" version = "0.3.74" @@ -482,24 +288,12 @@ dependencies = [ "addr2line", "cfg-if", "libc", - "miniz_oxide 0.8.0", + "miniz_oxide", "object", "rustc-demangle", "windows-targets 0.52.6", ] -[[package]] -name = "base16ct" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf" - -[[package]] -name = "base64" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" - [[package]] name = "base64" version = "0.21.7" @@ -519,20 +313,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] -name = "bincode" -version = "1.3.3" +name = "bigdecimal" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad" +checksum = "7f31f3af01c5c65a07985c804d3366560e6fa7883d640a122819b14ec327482c" dependencies = [ + "autocfg", + "libm", + "num-bigint", + "num-integer", + "num-traits", "serde", ] -[[package]] -name = "bit_field" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" - [[package]] name = "bitflags" version = "1.3.2" @@ -549,29 +342,15 @@ dependencies = [ ] [[package]] -name = "bitstream-io" -version = "2.5.3" +name = "bitvec" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b81e1519b0d82120d2fd469d5bfb2919a9361c48b02d82d04befc1cdd2002452" - -[[package]] -name = "blake2" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe" +checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" dependencies = [ - "digest", -] - -[[package]] -name = "blake2b_simd" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23285ad32269793932e830392f2fe2f83e26488fd3ec778883a93c8323735780" -dependencies = [ - "arrayref", - "arrayvec", - "constant_time_eq 0.3.1", + "funty", + "radium", + "tap", + "wyz", ] [[package]] @@ -589,15 +368,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block-padding" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" -dependencies = [ - "generic-array", -] - [[package]] name = "block2" version = "0.5.1" @@ -608,16 +378,27 @@ dependencies = [ ] [[package]] -name = "blocking" -version = "1.6.1" +name = "borsh" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "703f41c54fc768e63e091340b424302bb1c29ef4aa0c7f10fe849dfb114d29ea" +checksum = "26d4d6dafc1a3bb54687538972158f07b2c948bc57d5890df22c0739098b3028" dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", + "borsh-derive", + "cfg_aliases 0.1.1", +] + +[[package]] +name = "borsh-derive" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf4918709cc4dd777ad2b6303ed03cb37f3ca0ccede8c1b0d28ac6db8f4710e0" +dependencies = [ + "once_cell", + "proc-macro-crate 2.0.2", + "proc-macro2", + "quote", + "syn 2.0.87", + "syn_derive", ] [[package]] @@ -641,18 +422,34 @@ dependencies = [ "alloc-stdlib", ] -[[package]] -name = "built" -version = "0.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" - [[package]] name = "bumpalo" version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" +[[package]] +name = "bytecheck" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" +dependencies = [ + "bytecheck_derive", + "ptr_meta", + "simdutf8", +] + +[[package]] +name = "bytecheck_derive" +version = "0.6.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "bytemuck" version = "1.18.0" @@ -665,12 +462,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "byteorder-lite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" - [[package]] name = "bytes" version = "1.10.1" @@ -812,36 +603,18 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "cfg_aliases" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" -[[package]] -name = "chacha20" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" -dependencies = [ - "cfg-if", - "cipher", - "cpufeatures", -] - -[[package]] -name = "chacha20poly1305" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" -dependencies = [ - "aead", - "chacha20", - "cipher", - "poly1305", - "zeroize", -] - [[package]] name = "chrono" version = "0.4.38" @@ -865,18 +638,48 @@ checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ "crypto-common", "inout", - "zeroize", ] [[package]] -name = "clipboard-win" -version = "5.4.0" +name = "clap" +version = "4.5.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892" +checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff" dependencies = [ - "error-code", + "clap_builder", + "clap_derive", ] +[[package]] +name = "clap_builder" +version = "4.5.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7" +dependencies = [ + "heck 0.5.0", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "clap_lex" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" + [[package]] name = "cocoa" version = "0.26.0" @@ -887,7 +690,7 @@ dependencies = [ "block", "cocoa-foundation", "core-foundation 0.10.0", - "core-graphics 0.24.0", + "core-graphics", "foreign-types", "libc", "objc", @@ -902,16 +705,16 @@ dependencies = [ "bitflags 2.6.0", "block", "core-foundation 0.10.0", - "core-graphics-types 0.2.0", + "core-graphics-types", "libc", "objc", ] [[package]] -name = "color_quant" -version = "1.1.0" +name = "colorchoice" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" @@ -951,32 +754,6 @@ version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" -[[package]] -name = "const-random" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87e00182fe74b066627d63b85fd550ac2998d4b0bd86bfed477a0ae4c7c71359" -dependencies = [ - "const-random-macro", -] - -[[package]] -name = "const-random-macro" -version = "0.1.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d839f2a20b0aee515dc581a6172f2321f96cab76c1a38a4c584a194955390e" -dependencies = [ - "getrandom 0.2.15", - "once_cell", - "tiny-keccak", -] - -[[package]] -name = "constant_time_eq" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" - [[package]] name = "constant_time_eq" version = "0.3.1" @@ -1015,19 +792,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "foreign-types", - "libc", -] - [[package]] name = "core-graphics" version = "0.24.0" @@ -1036,22 +800,11 @@ checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ "bitflags 2.6.0", "core-foundation 0.10.0", - "core-graphics-types 0.2.0", + "core-graphics-types", "foreign-types", "libc", ] -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - [[package]] name = "core-graphics-types" version = "0.2.0" @@ -1063,15 +816,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core2" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" -dependencies = [ - "memchr", -] - [[package]] name = "cpufeatures" version = "0.2.14" @@ -1148,24 +892,6 @@ version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" -[[package]] -name = "crunchy" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" - -[[package]] -name = "crypto-bigint" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76" -dependencies = [ - "generic-array", - "rand_core 0.6.4", - "subtle", - "zeroize", -] - [[package]] name = "crypto-common" version = "0.1.6" @@ -1213,42 +939,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "ctr" -version = "0.9.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" -dependencies = [ - "cipher", -] - -[[package]] -name = "curve25519-dalek" -version = "4.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" -dependencies = [ - "cfg-if", - "cpufeatures", - "curve25519-dalek-derive", - "digest", - "fiat-crypto", - "rustc_version", - "subtle", - "zeroize", -] - -[[package]] -name = "curve25519-dalek-derive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "darling" version = "0.20.10" @@ -1284,18 +974,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "dary_heap" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7762d17f1241643615821a8455a0b2c3e803784b058693d990b11f2dce25a0ca" - -[[package]] -name = "data-encoding" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8566979429cf69b49a5c740c60791108e86440e8be149bbea4fe54d2c32d6e2" - [[package]] name = "deflate64" version = "0.1.9" @@ -1323,17 +1001,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - [[package]] name = "derive_arbitrary" version = "1.3.2" @@ -1370,43 +1037,13 @@ dependencies = [ "subtle", ] -[[package]] -name = "dirs" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" -dependencies = [ - "dirs-sys 0.3.7", -] - [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys 0.4.1", -] - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" -dependencies = [ - "libc", - "redox_users", - "winapi", + "dirs-sys", ] [[package]] @@ -1421,17 +1058,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - [[package]] name = "discord-rich-presence" version = "0.2.4" @@ -1461,15 +1087,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "dlib" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412" -dependencies = [ - "libloading", -] - [[package]] name = "dlopen2" version = "0.7.0" @@ -1493,32 +1110,12 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "dlv-list" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "442039f5147480ba31067cb00ada1adae6892028e40e45fc5de7b7df6dcc1b5f" -dependencies = [ - "const-random", -] - [[package]] name = "dotenvy" version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" -[[package]] -name = "dotenvy" -version = "0.15.7" -source = "git+https://github.com/allan2/dotenvy/?rev=db0d6aa8fc8d1b0ddbfe94b5c833372e463eb1c5#db0d6aa8fc8d1b0ddbfe94b5c833372e463eb1c5" - -[[package]] -name = "downcast-rs" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" - [[package]] name = "dpi" version = "0.1.1" @@ -1555,44 +1152,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" -[[package]] -name = "ecdsa" -version = "0.16.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca" -dependencies = [ - "der", - "digest", - "elliptic-curve", - "rfc6979", - "signature", - "spki", -] - -[[package]] -name = "ed25519" -version = "2.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53" -dependencies = [ - "signature", -] - -[[package]] -name = "ed25519-zebra" -version = "4.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d9ce6874da5d4415896cd45ffbc4d1cfc0c4f9c079427bd870742c30f2f65a9" -dependencies = [ - "curve25519-dalek", - "ed25519", - "hashbrown 0.14.5", - "hex", - "rand_core 0.6.4", - "sha2", - "zeroize", -] - [[package]] name = "either" version = "1.13.0" @@ -1602,26 +1161,6 @@ dependencies = [ "serde", ] -[[package]] -name = "elliptic-curve" -version = "0.13.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47" -dependencies = [ - "base16ct", - "crypto-bigint", - "digest", - "ff", - "generic-array", - "group", - "pem-rfc7468", - "pkcs8", - "rand_core 0.6.4", - "sec1", - "subtle", - "zeroize", -] - [[package]] name = "embed-resource" version = "2.5.0" @@ -1657,33 +1196,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "endi" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3d8a32ae18130a3c84dd492d4215c3d913c3b07c6b63c2eb3eb7ff1101ab7bf" - -[[package]] -name = "enumflags2" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d232db7f5956f3f14313dc2f87985c58bd2c695ce124c8cdd984e08e15ac133d" -dependencies = [ - "enumflags2_derive", - "serde", -] - -[[package]] -name = "enumflags2_derive" -version = "0.7.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de0d48a183585823424a4ce1aa132d174a6a81bd540895822eb4c8373a8e49e8" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "equivalent" version = "1.0.1" @@ -1710,12 +1222,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "error-code" -version = "3.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f" - [[package]] name = "etcetera" version = "0.8.0" @@ -1738,32 +1244,6 @@ dependencies = [ "pin-project-lite", ] -[[package]] -name = "event-listener-strategy" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" -dependencies = [ - "event-listener", - "pin-project-lite", -] - -[[package]] -name = "exr" -version = "1.72.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "887d93f60543e9a9362ef8a21beedd0a833c5d9610e18c67abe15a5963dcb1a4" -dependencies = [ - "bit_field", - "flume", - "half", - "lebe", - "miniz_oxide 0.7.4", - "rayon-core", - "smallvec", - "zune-inflate", -] - [[package]] name = "fastrand" version = "2.1.1" @@ -1779,44 +1259,16 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "ff" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449" -dependencies = [ - "rand_core 0.6.4", - "subtle", -] - -[[package]] -name = "fiat-crypto" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28dea519a9695b9977216879a3ebfddf92f1c08c05d984f8996aecd6ecdc811d" - [[package]] name = "field-offset" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" dependencies = [ - "memoffset 0.9.1", + "memoffset", "rustc_version", ] -[[package]] -name = "filetime" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" -dependencies = [ - "cfg-if", - "libc", - "libredox", - "windows-sys 0.59.0", -] - [[package]] name = "flate2" version = "1.0.34" @@ -1824,7 +1276,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", - "miniz_oxide 0.8.0", + "miniz_oxide", ] [[package]] @@ -1896,13 +1348,10 @@ dependencies = [ ] [[package]] -name = "fsevent-sys" -version = "4.1.0" +name = "funty" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" -dependencies = [ - "libc", -] +checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "futf" @@ -2143,17 +1592,6 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", - "zeroize", -] - -[[package]] -name = "gethostname" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818" -dependencies = [ - "libc", - "windows-targets 0.48.5", ] [[package]] @@ -2174,30 +1612,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", -] - -[[package]] -name = "ghash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" -dependencies = [ - "opaque-debug", - "polyval", -] - -[[package]] -name = "gif" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" -dependencies = [ - "color_quant", - "weezl", ] [[package]] @@ -2302,17 +1718,6 @@ dependencies = [ "system-deps", ] -[[package]] -name = "group" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63" -dependencies = [ - "ff", - "rand_core 0.6.4", - "subtle", -] - [[package]] name = "gtk" version = "0.18.1" @@ -2384,31 +1789,20 @@ dependencies = [ "tracing", ] -[[package]] -name = "half" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" -dependencies = [ - "cfg-if", - "crunchy", -] - [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +dependencies = [ + "ahash", +] [[package]] name = "hashbrown" version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" -dependencies = [ - "ahash", - "allocator-api2", -] [[package]] name = "hashbrown" @@ -2448,12 +1842,6 @@ version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" -[[package]] -name = "hermit-abi" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" - [[package]] name = "hex" version = "0.4.3" @@ -2653,45 +2041,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "image" -version = "0.25.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99314c8a2152b8ddb211f924cdae532d8c5e4c8bb54728e12fff1b0cd5963a10" -dependencies = [ - "bytemuck", - "byteorder-lite", - "color_quant", - "exr", - "gif", - "image-webp", - "num-traits", - "png", - "qoi", - "ravif", - "rayon", - "rgb", - "tiff", - "zune-core", - "zune-jpeg", -] - -[[package]] -name = "image-webp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79afb8cbee2ef20f59ccd477a218c12a93943d075b492015ecb1bb81f8ee904" -dependencies = [ - "byteorder-lite", - "quick-error", -] - -[[package]] -name = "imgref" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" - [[package]] name = "indexmap" version = "1.9.3" @@ -2737,23 +2086,14 @@ dependencies = [ ] [[package]] -name = "inotify" -version = "0.9.6" +name = "inherent" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "6c38228f24186d9cc68c729accb4d413be9eaed6ad07ff79e0270d9e56f3de13" dependencies = [ - "bitflags 1.3.2", - "inotify-sys", - "libc", -] - -[[package]] -name = "inotify-sys" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" -dependencies = [ - "libc", + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] @@ -2762,7 +2102,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5" dependencies = [ - "block-padding", "generic-array", ] @@ -2775,17 +2114,6 @@ dependencies = [ "cfg-if", ] -[[package]] -name = "interpolate_name" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "interpulse" version = "1.2.2" @@ -2800,58 +2128,6 @@ dependencies = [ "thiserror 2.0.12", ] -[[package]] -name = "iota-crypto" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a38db844c910d78825e173c083f2ef416b69cb091bba8ac1055763c6db065b" -dependencies = [ - "aead", - "aes", - "aes-gcm", - "autocfg", - "base64 0.21.7", - "blake2", - "chacha20poly1305", - "cipher", - "curve25519-dalek", - "digest", - "ed25519-zebra", - "generic-array", - "getrandom 0.2.15", - "hkdf", - "hmac", - "iterator-sorted", - "k256", - "pbkdf2", - "rand 0.8.5", - "scrypt", - "serde", - "sha2", - "tiny-keccak", - "unicode-normalization", - "x25519-dalek", - "zeroize", -] - -[[package]] -name = "iota_stronghold" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c0d301c7edbc31494d183b7d24c1bb51d3fb10fce2f3793df1baf45b6988e10" -dependencies = [ - "bincode", - "hkdf", - "iota-crypto", - "rust-argon2", - "serde", - "stronghold-derive", - "stronghold-utils", - "stronghold_engine", - "thiserror 1.0.64", - "zeroize", -] - [[package]] name = "ipnet" version = "2.10.0" @@ -2859,38 +2135,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "187674a687eed5fe42285b40c6291f9a01517d415fad1c3cbc6a9f778af7fcd4" [[package]] -name = "is-docker" -version = "0.2.0" +name = "is_terminal_polyfill" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3" -dependencies = [ - "once_cell", -] - -[[package]] -name = "is-wsl" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5" -dependencies = [ - "is-docker", - "once_cell", -] - -[[package]] -name = "iterator-sorted" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d101775d2bc8f99f4ac18bf29b9ed70c0dd138b9a1e88d7b80179470cbbe8bd2" - -[[package]] -name = "itertools" -version = "0.12.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" -dependencies = [ - "either", -] +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" @@ -2958,12 +2206,6 @@ dependencies = [ "libc", ] -[[package]] -name = "jpeg-decoder" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" - [[package]] name = "js-sys" version = "0.3.70" @@ -2996,19 +2238,6 @@ dependencies = [ "serde_json", ] -[[package]] -name = "k256" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" -dependencies = [ - "cfg-if", - "ecdsa", - "elliptic-curve", - "once_cell", - "sha2", -] - [[package]] name = "keyboard-types" version = "0.7.0" @@ -3020,26 +2249,6 @@ dependencies = [ "unicode-segmentation", ] -[[package]] -name = "kqueue" -version = "1.0.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" -dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", -] - [[package]] name = "kuchikiki" version = "0.8.2" @@ -3062,12 +2271,6 @@ dependencies = [ "spin", ] -[[package]] -name = "lebe" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" - [[package]] name = "libappindicator" version = "0.9.0" @@ -3098,41 +2301,6 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" -[[package]] -name = "libflate" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45d9dfdc14ea4ef0900c1cddbc8dcd553fbaacd8a4a282cf4018ae9dd04fb21e" -dependencies = [ - "adler32", - "core2", - "crc32fast", - "dary_heap", - "libflate_lz77", -] - -[[package]] -name = "libflate_lz77" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e0d73b369f386f1c44abd9c570d5318f55ccde816ff4b562fa452e5182863d" -dependencies = [ - "core2", - "hashbrown 0.14.5", - "rle-decode-fast", -] - -[[package]] -name = "libfuzzer-sys" -version = "0.4.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a96cfd5557eb82f2b83fed4955246c988d331975a002961b07c81584d107e7f7" -dependencies = [ - "arbitrary", - "cc", - "once_cell", -] - [[package]] name = "libloading" version = "0.7.4" @@ -3149,16 +2317,6 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" -[[package]] -name = "libmimalloc-sys" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23aa6811d3bd4deb8a84dde645f943476d13b248d818edcf8ce0b2f37f036b44" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "libredox" version = "0.1.3" @@ -3167,24 +2325,6 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall", -] - -[[package]] -name = "libsodium-sys-stable" -version = "1.21.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42631d334de875c636a1aae7adb515653ac2e771e5a2ce74b1053f5a4412df3a" -dependencies = [ - "cc", - "libc", - "libflate", - "minisign-verify", - "pkg-config", - "tar", - "ureq", - "vcpkg", - "zip", ] [[package]] @@ -3226,15 +2366,6 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" -[[package]] -name = "loop9" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" -dependencies = [ - "imgref", -] - [[package]] name = "lzma-rs" version = "0.3.0" @@ -3300,15 +2431,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "maybe-rayon" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" -dependencies = [ - "cfg-if", -] - [[package]] name = "md-5" version = "0.10.6" @@ -3331,15 +2453,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.9.1" @@ -3349,15 +2462,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "mimalloc" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68914350ae34959d83f732418d51e2427a794055d0b9529f48259ac07af65633" -dependencies = [ - "libmimalloc-sys", -] - [[package]] name = "mime" version = "0.3.17" @@ -3374,27 +2478,6 @@ dependencies = [ "unicase", ] -[[package]] -name = "minimal-lexical" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" - -[[package]] -name = "minisign-verify" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a05b5d0594e0cb1ad8cee3373018d2b84e25905dc75b2468114cc9a8e86cfc20" - -[[package]] -name = "miniz_oxide" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" -dependencies = [ - "adler", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -3405,25 +2488,13 @@ dependencies = [ "simd-adler32", ] -[[package]] -name = "mio" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" -dependencies = [ - "libc", - "log", - "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys 0.48.0", -] - [[package]] name = "mio" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ - "hermit-abi 0.3.9", + "hermit-abi", "libc", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", @@ -3491,81 +2562,12 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.27.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" -dependencies = [ - "bitflags 2.6.0", - "cfg-if", - "libc", - "memoffset 0.9.1", -] - [[package]] name = "nodrop" 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 = "noop_proc_macro" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" - -[[package]] -name = "notify" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" -dependencies = [ - "bitflags 2.6.0", - "crossbeam-channel", - "filetime", - "fsevent-sys", - "inotify", - "kqueue", - "libc", - "log", - "mio 0.8.11", - "walkdir", - "windows-sys 0.48.0", -] - -[[package]] -name = "notify-debouncer-mini" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d40b221972a1fc5ef4d858a2f671fb34c75983eb385463dff3780eeff6a9d43" -dependencies = [ - "log", - "notify", -] - [[package]] name = "ntapi" version = "0.4.1" @@ -3618,17 +2620,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-derive" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.87", -] - [[package]] name = "num-integer" version = "0.1.46" @@ -3649,17 +2640,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "num-rational" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" -dependencies = [ - "num-bigint", - "num-integer", - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -3815,7 +2795,6 @@ checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ "bitflags 2.6.0", "block2", - "dispatch", "libc", "objc2", ] @@ -3941,121 +2920,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] -name = "onelauncher" -version = "0.1.0-alpha.2" -dependencies = [ - "anyhow", - "async-recursion", - "async-tungstenite", - "async_zip", - "base64 0.22.1", - "byteorder", - "bytes", - "chrono", - "dirs 5.0.1", - "discord-rich-presence", - "dotenvy 0.15.7 (git+https://github.com/allan2/dotenvy/?rev=db0d6aa8fc8d1b0ddbfe94b5c833372e463eb1c5)", - "flate2", - "futures", - "indicatif", - "interpulse", - "iota_stronghold", - "lazy_static", - "md5", - "murmur2", - "notify", - "notify-debouncer-mini", - "onelauncher_gamemode", - "onelauncher_macros", - "onelauncher_utils", - "p256", - "paste", - "rand 0.8.5", - "regex", - "reqwest", - "serde", - "serde_ini", - "serde_json", - "serde_repr", - "serde_with", - "sha1_smol", - "sha2", - "specta", - "sysinfo", - "tauri", - "tauri-specta", - "tempfile", - "thiserror 1.0.64", - "tokio", - "tokio-stream", - "toml 0.8.2", - "tracing", - "tracing-appender", - "tracing-error", - "tracing-subscriber", - "url", - "uuid 1.10.0", - "whoami", - "winreg", - "zeroize", - "zip", -] - -[[package]] -name = "onelauncher_gamemode" -version = "0.1.0-alpha.2" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "onelauncher_gui" -version = "0.1.0-alpha.2" -dependencies = [ - "anyhow", - "chrono", - "cocoa", - "interpulse", - "mimalloc", - "objc", - "once_cell", - "onelauncher", - "onelauncher_macros", - "serde", - "serde_json", - "specta", - "specta-typescript", - "strum", - "tauri", - "tauri-build", - "tauri-plugin-clipboard-manager", - "tauri-plugin-deep-link", - "tauri-plugin-dialog", - "tauri-plugin-shell", - "tauri-plugin-single-instance", - "tauri-plugin-updater", - "tauri-plugin-window-state", - "tauri-specta", - "thiserror 1.0.64", - "tokio", - "tracing", - "tracing-error", - "uuid 1.10.0", - "webkit2gtk", -] - -[[package]] -name = "onelauncher_macros" -version = "0.1.0-alpha.2" -dependencies = [ - "quote", - "syn 2.0.87", -] - -[[package]] -name = "onelauncher_new" -version = "0.1.0-alpha.2" +name = "onelauncher_core" +version = "0.2.0-alpha.2" dependencies = [ "anyhow", "async-compression", @@ -4064,19 +2930,22 @@ dependencies = [ "base64 0.22.1", "bytes", "chrono", - "dirs 5.0.1", + "dirs", "discord-rich-presence", "dunce", "futures", "indicatif", "interpulse", - "lazy_static", "md5", "murmur2", + "onelauncher_entity", "onelauncher_gamemode", + "onelauncher_macro", + "onelauncher_migration", "rand 0.8.5", "regex", "reqwest", + "sea-orm", "serde", "serde_ini", "serde_json", @@ -4085,7 +2954,6 @@ dependencies = [ "sha1_smol", "sha2", "specta", - "sqlx", "sysinfo", "tauri", "tauri-specta", @@ -4103,53 +2971,41 @@ dependencies = [ ] [[package]] -name = "onelauncher_test" -version = "0.1.0-alpha.2" +name = "onelauncher_entity" +version = "0.2.0-alpha.2" dependencies = [ - "onelauncher", - "tokio", - "url", - "webbrowser", -] - -[[package]] -name = "onelauncher_utils" -version = "0.1.0-alpha.2" -dependencies = [ - "async-channel", - "async-compression", "chrono", - "dunce", - "futures", - "interpulse", - "nom", - "pin-project-lite", - "regex", + "onelauncher_macro", + "sea-orm", "serde", - "sys-info", - "tempfile", - "thiserror 1.0.64", - "tokio", - "tracing", + "serde_json", + "specta", "uuid 1.10.0", - "zip", ] [[package]] -name = "opaque-debug" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +name = "onelauncher_gamemode" +version = "0.2.0-alpha.2" +dependencies = [ + "cc", + "libc", +] [[package]] -name = "open" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a877bf6abd716642a53ef1b89fb498923a4afca5c754f9050b4d081c05c4b3" +name = "onelauncher_macro" +version = "0.2.0-alpha.2" dependencies = [ - "is-wsl", - "libc", - "pathdiff", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "onelauncher_migration" +version = "0.2.0-alpha.2" +dependencies = [ + "async-trait", + "sea-orm-migration", + "tokio", ] [[package]] @@ -4159,33 +3015,36 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] -name = "ordered-multimap" -version = "0.7.3" +name = "ordered-float" +version = "4.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49203cdcae0030493bad186b28da2fa25645fa276a51b6fec8010d281e02ef79" +checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" dependencies = [ - "dlv-list", - "hashbrown 0.14.5", + "num-traits", ] [[package]] -name = "ordered-stream" -version = "0.2.0" +name = "ouroboros" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aa2b01e1d916879f73a53d01d1d6cee68adbb31d6d9177a8cfce093cced1d50" +checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59" dependencies = [ - "futures-core", - "pin-project-lite", + "aliasable", + "ouroboros_macro", + "static_assertions", ] [[package]] -name = "os_pipe" -version = "1.2.1" +name = "ouroboros_macro" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ffd2b0a5634335b135d5728d84c5e0fd726954b87111f7506a61c502280d982" +checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0" dependencies = [ - "libc", - "windows-sys 0.59.0", + "heck 0.4.1", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.87", ] [[package]] @@ -4194,18 +3053,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" -[[package]] -name = "p256" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b" -dependencies = [ - "ecdsa", - "elliptic-curve", - "primeorder", - "sha2", -] - [[package]] name = "pango" version = "0.18.3" @@ -4266,12 +3113,6 @@ version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" -[[package]] -name = "pathdiff" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" - [[package]] name = "pbkdf2" version = "0.12.2" @@ -4297,6 +3138,15 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pgvector" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0e8871b6d7ca78348c6cd29b911b94851f3429f0cd403130ca17f26c1fb91a6" +dependencies = [ + "serde", +] + [[package]] name = "phf" version = "0.8.0" @@ -4463,17 +3313,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "piper" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkcs1" version = "0.7.5" @@ -4509,7 +3348,7 @@ checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", "indexmap 2.5.0", - "quick-xml 0.32.0", + "quick-xml", "serde", "time", ] @@ -4524,45 +3363,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide 0.8.0", -] - -[[package]] -name = "polling" -version = "3.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi 0.4.0", - "pin-project-lite", - "rustix", - "tracing", - "windows-sys 0.59.0", -] - -[[package]] -name = "poly1305" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" -dependencies = [ - "cpufeatures", - "opaque-debug", - "universal-hash", -] - -[[package]] -name = "polyval" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1fe60d06143b2430aa532c94cfe9e29783047f06c0d7fd359a9a51b729fa25" -dependencies = [ - "cfg-if", - "cpufeatures", - "opaque-debug", - "universal-hash", + "miniz_oxide", ] [[package]] @@ -4592,15 +3393,6 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" -[[package]] -name = "primeorder" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6" -dependencies = [ - "elliptic-curve", -] - [[package]] name = "proc-macro-crate" version = "1.3.1" @@ -4645,6 +3437,28 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -4661,38 +3475,37 @@ dependencies = [ ] [[package]] -name = "profiling" -version = "1.0.16" +name = "proc-macro2-diagnostics" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" -dependencies = [ - "profiling-procmacros", -] - -[[package]] -name = "profiling-procmacros" -version = "1.0.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ + "proc-macro2", "quote", "syn 2.0.87", + "version_check", + "yansi", ] [[package]] -name = "qoi" -version = "0.4.1" +name = "ptr_meta" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" dependencies = [ - "bytemuck", + "ptr_meta_derive", ] [[package]] -name = "quick-error" -version = "2.0.1" +name = "ptr_meta_derive" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" +checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] name = "quick-xml" @@ -4703,15 +3516,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "quick-xml" -version = "0.36.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" -dependencies = [ - "memchr", -] - [[package]] name = "quinn" version = "0.11.5" @@ -4769,6 +3573,12 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "radium" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" + [[package]] name = "rand" version = "0.7.3" @@ -4850,55 +3660,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rav1e" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" -dependencies = [ - "arbitrary", - "arg_enum_proc_macro", - "arrayvec", - "av1-grain", - "bitstream-io", - "built", - "cfg-if", - "interpolate_name", - "itertools", - "libc", - "libfuzzer-sys", - "log", - "maybe-rayon", - "new_debug_unreachable", - "noop_proc_macro", - "num-derive", - "num-traits", - "once_cell", - "paste", - "profiling", - "rand 0.8.5", - "rand_chacha 0.3.1", - "simd_helpers", - "system-deps", - "thiserror 1.0.64", - "v_frame", - "wasm-bindgen", -] - -[[package]] -name = "ravif" -version = "0.11.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" -dependencies = [ - "avif-serialize", - "imgref", - "loop9", - "quick-error", - "rav1e", - "rgb", -] - [[package]] name = "raw-window-handle" version = "0.6.2" @@ -4989,6 +3750,15 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +[[package]] +name = "rend" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" +dependencies = [ + "bytecheck", +] + [[package]] name = "reqwest" version = "0.12.7" @@ -5036,7 +3806,7 @@ dependencies = [ "wasm-streams", "web-sys", "webpki-roots", - "windows-registry 0.2.0", + "windows-registry", ] [[package]] @@ -5045,48 +3815,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "194d8e591e405d1eecf28819740abed6d719d1a2db87fc0bcdedee9a26d55560" -[[package]] -name = "rfc6979" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2" -dependencies = [ - "hmac", - "subtle", -] - -[[package]] -name = "rfd" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8af382a047821a08aa6bfc09ab0d80ff48d45d8726f7cd8e44891f7cb4a4278e" -dependencies = [ - "ashpd", - "block2", - "glib-sys", - "gobject-sys", - "gtk-sys", - "js-sys", - "log", - "objc2", - "objc2-app-kit", - "objc2-foundation", - "raw-window-handle", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "rgb" -version = "0.8.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" -dependencies = [ - "bytemuck", -] - [[package]] name = "ring" version = "0.17.8" @@ -5103,10 +3831,33 @@ dependencies = [ ] [[package]] -name = "rle-decode-fast" -version = "1.0.3" +name = "rkyv" +version = "0.7.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422" +checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" +dependencies = [ + "bitvec", + "bytecheck", + "bytes", + "hashbrown 0.12.3", + "ptr_meta", + "rend", + "rkyv_derive", + "seahash", + "tinyvec", + "uuid 1.10.0", +] + +[[package]] +name = "rkyv_derive" +version = "0.7.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" +dependencies = [ + "proc-macro2", + "quote", + "syn 1.0.109", +] [[package]] name = "rsa" @@ -5129,26 +3880,19 @@ dependencies = [ ] [[package]] -name = "rust-argon2" -version = "1.0.0" +name = "rust_decimal" +version = "1.37.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b50162d19404029c1ceca6f6980fe40d45c8b369f6f44446fa14bb39573b5bb9" +checksum = "faa7de2ba56ac291bd90c6b9bece784a52ae1411f9506544b3eae36dd2356d50" dependencies = [ - "base64 0.13.1", - "blake2b_simd", - "constant_time_eq 0.1.5", - "crossbeam-utils", -] - -[[package]] -name = "rust-ini" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e310ef0e1b6eeb79169a1171daf9abcb87a2e17c03bee2c4bb100b55c75409f" -dependencies = [ - "cfg-if", - "ordered-multimap", - "trim-in-place", + "arrayvec", + "borsh", + "bytes", + "num-traits", + "rand 0.8.5", + "rkyv", + "serde", + "serde_json", ] [[package]] @@ -5226,27 +3970,12 @@ dependencies = [ "untrusted", ] -[[package]] -name = "rustversion" -version = "1.0.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" - [[package]] name = "ryu" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - [[package]] name = "same-file" version = "1.0.6" @@ -5283,12 +4012,6 @@ dependencies = [ "syn 2.0.87", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" @@ -5296,30 +4019,170 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "scrypt" -version = "0.11.0" +name = "sea-bae" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +checksum = "f694a6ab48f14bc063cfadff30ab551d3c7e46d8f81836c51989d548f44a2a25" dependencies = [ - "pbkdf2", - "salsa20", - "sha2", + "heck 0.4.1", + "proc-macro-error2", + "proc-macro2", + "quote", + "syn 2.0.87", ] [[package]] -name = "sec1" -version = "0.7.3" +name = "sea-orm" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc" +checksum = "3417812d38049e8ec3d588c03570f8c60de811d2453fb48e424045a1600ffd86" dependencies = [ - "base16ct", - "der", - "generic-array", - "pkcs8", - "subtle", - "zeroize", + "async-stream", + "async-trait", + "bigdecimal", + "chrono", + "futures-util", + "log", + "ouroboros", + "pgvector", + "rust_decimal", + "sea-orm-macros", + "sea-query", + "sea-query-binder", + "serde", + "serde_json", + "sqlx", + "strum", + "thiserror 1.0.64", + "time", + "tracing", + "url", + "uuid 1.10.0", ] +[[package]] +name = "sea-orm-cli" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf2a390d6528f8e5c9ecd327bbb1a4c6cd7ab8333ef0da97010d5dc8f83f01c4" +dependencies = [ + "chrono", + "clap", + "dotenvy", + "glob", + "regex", + "sea-schema", + "tracing", + "tracing-subscriber", + "url", +] + +[[package]] +name = "sea-orm-macros" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d705ba84e1c74c8ac27784e4ac6f21584058c1dc0cadb9d39b43e109fcf8139c" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "sea-bae", + "syn 2.0.87", + "unicode-ident", +] + +[[package]] +name = "sea-orm-migration" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c38451d5112e3a518a02251b5e6d3bc72e626957a44a79264716808a4c28ee0" +dependencies = [ + "async-trait", + "clap", + "dotenvy", + "sea-orm", + "sea-orm-cli", + "sea-schema", + "tracing", + "tracing-subscriber", +] + +[[package]] +name = "sea-query" +version = "0.32.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5a24d8b9fcd2674a6c878a3d871f4f1380c6c43cc3718728ac96864d888458e" +dependencies = [ + "bigdecimal", + "chrono", + "inherent", + "ordered-float", + "rust_decimal", + "sea-query-derive", + "serde_json", + "time", + "uuid 1.10.0", +] + +[[package]] +name = "sea-query-binder" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0019f47430f7995af63deda77e238c17323359af241233ec768aba1faea7608" +dependencies = [ + "bigdecimal", + "chrono", + "rust_decimal", + "sea-query", + "serde_json", + "sqlx", + "time", + "uuid 1.10.0", +] + +[[package]] +name = "sea-query-derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bae0cbad6ab996955664982739354128c58d16e126114fe88c2a493642502aab" +dependencies = [ + "darling", + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.87", + "thiserror 2.0.12", +] + +[[package]] +name = "sea-schema" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef5dd7848c993f3789d09a2616484c72c9330cae2b048df59d8c9b8c0343e95" +dependencies = [ + "futures", + "sea-query", + "sea-schema-derive", +] + +[[package]] +name = "sea-schema-derive" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debdc8729c37fdbf88472f97fd470393089f997a909e535ff67c544d18cfccf0" +dependencies = [ + "heck 0.4.1", + "proc-macro2", + "quote", + "syn 2.0.87", +] + +[[package]] +name = "seahash" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" + [[package]] name = "selectors" version = "0.22.0" @@ -5545,16 +4408,6 @@ dependencies = [ "lazy_static", ] -[[package]] -name = "shared_child" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09fa9338aed9a1df411814a5b2252f7cd206c55ae9bf2fa763f8de84603aa60c" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "shlex" version = "1.3.0" @@ -5587,13 +4440,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" [[package]] -name = "simd_helpers" -version = "0.1.0" +name = "simdutf8" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" -dependencies = [ - "quote", -] +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "siphasher" @@ -5636,8 +4486,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18051cdd562e792cad055119e0cdb2cfc137e44e3987532e0f9659a77931bb08" dependencies = [ "bytemuck", - "cfg_aliases", - "core-graphics 0.24.0", + "cfg_aliases 0.2.1", + "core-graphics", "foreign-types", "js-sys", "log", @@ -5775,6 +4625,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" dependencies = [ + "bigdecimal", "bytes", "chrono", "crc", @@ -5792,16 +4643,21 @@ dependencies = [ "memchr", "once_cell", "percent-encoding", + "rust_decimal", + "rustls", + "rustls-pemfile", "serde", "serde_json", "sha2", "smallvec", "thiserror 2.0.12", + "time", "tokio", "tokio-stream", "tracing", "url", "uuid 1.10.0", + "webpki-roots", ] [[package]] @@ -5823,7 +4679,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" dependencies = [ - "dotenvy 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", + "dotenvy", "either", "heck 0.5.0", "hex", @@ -5851,13 +4707,14 @@ checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" dependencies = [ "atoi", "base64 0.22.1", + "bigdecimal", "bitflags 2.6.0", "byteorder", "bytes", "chrono", "crc", "digest", - "dotenvy 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", + "dotenvy", "either", "futures-channel", "futures-core", @@ -5875,6 +4732,7 @@ dependencies = [ "percent-encoding", "rand 0.8.5", "rsa", + "rust_decimal", "serde", "sha1", "sha2", @@ -5882,6 +4740,7 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror 2.0.12", + "time", "tracing", "uuid 1.10.0", "whoami", @@ -5895,11 +4754,12 @@ checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" dependencies = [ "atoi", "base64 0.22.1", + "bigdecimal", "bitflags 2.6.0", "byteorder", "chrono", "crc", - "dotenvy 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)", + "dotenvy", "etcetera", "futures-channel", "futures-core", @@ -5912,8 +4772,10 @@ dependencies = [ "log", "md-5", "memchr", + "num-bigint", "once_cell", "rand 0.8.5", + "rust_decimal", "serde", "serde_json", "sha2", @@ -5921,6 +4783,7 @@ dependencies = [ "sqlx-core", "stringprep", "thiserror 2.0.12", + "time", "tracing", "uuid 1.10.0", "whoami", @@ -5946,6 +4809,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", + "time", "tracing", "url", "uuid 1.10.0", @@ -6000,64 +4864,6 @@ dependencies = [ "unicode-properties", ] -[[package]] -name = "stronghold-derive" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2835db23c4724c05a2f85b81c4681f4aa8ea158edc8a7f4ad791c916fb766c2e" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] - -[[package]] -name = "stronghold-runtime" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18db7cc51450cefdab5f4990e128dd02c98da6d2992b93ffef8992ac0d2f3ddf" -dependencies = [ - "dirs 4.0.0", - "iota-crypto", - "libc", - "libsodium-sys-stable", - "log", - "nix 0.24.3", - "rand 0.8.5", - "serde", - "thiserror 1.0.64", - "windows 0.36.1", - "zeroize", -] - -[[package]] -name = "stronghold-utils" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8300214898af5e153e7f66e49dbd1c6a21585f2d592d9f24f58b969792475ed6" -dependencies = [ - "rand 0.8.5", - "stronghold-derive", -] - -[[package]] -name = "stronghold_engine" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd7371c42e557dd71a7f860bb2ec6b6fdb32f97a97987ccc2435fdd1f3a8615" -dependencies = [ - "anyhow", - "dirs-next", - "hex", - "iota-crypto", - "once_cell", - "paste", - "serde", - "stronghold-runtime", - "thiserror 1.0.64", - "zeroize", -] - [[package]] name = "strsim" version = "0.11.1" @@ -6069,22 +4875,6 @@ name = "strum" version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" -dependencies = [ - "strum_macros", -] - -[[package]] -name = "strum_macros" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" -dependencies = [ - "heck 0.5.0", - "proc-macro2", - "quote", - "rustversion", - "syn 2.0.87", -] [[package]] name = "subtle" @@ -6125,6 +4915,18 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.87", +] + [[package]] name = "sync_wrapper" version = "1.0.1" @@ -6134,16 +4936,6 @@ dependencies = [ "futures-core", ] -[[package]] -name = "sys-info" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b3a0d0aba8bf96a0e1ddfdc352fc53b3df7f39318c71854910c3c4b024ae52c" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "sysinfo" version = "0.31.4" @@ -6202,7 +4994,7 @@ dependencies = [ "bitflags 2.6.0", "cocoa", "core-foundation 0.10.0", - "core-graphics 0.24.0", + "core-graphics", "crossbeam-channel", "dispatch", "dlopen2", @@ -6244,15 +5036,10 @@ dependencies = [ ] [[package]] -name = "tar" -version = "0.4.42" +name = "tap" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ff6c40d3aedb5e06b57c6f669ad17ab063dd1e63d977c6a88e7f4dfa4f04020" -dependencies = [ - "filetime", - "libc", - "xattr", -] +checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" [[package]] name = "target-lexicon" @@ -6268,7 +5055,7 @@ checksum = "44438500b50708bfc1e6083844e135d1b516325aae58710dcd8fb67e050ae87c" dependencies = [ "anyhow", "bytes", - "dirs 5.0.1", + "dirs", "dunce", "embed_plist", "futures-util", @@ -6278,7 +5065,6 @@ dependencies = [ "heck 0.5.0", "http", "http-range", - "image", "jni", "libc", "log", @@ -6323,7 +5109,7 @@ checksum = "935f9b3c49b22b3e2e485a57f46d61cd1ae07b1cbb2ba87387a387caf2d8c4e7" dependencies = [ "anyhow", "cargo_toml", - "dirs 5.0.1", + "dirs", "glob", "heck 0.5.0", "json-patch", @@ -6378,179 +5164,6 @@ dependencies = [ "tauri-utils", ] -[[package]] -name = "tauri-plugin" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2e6660a409963e4d57b9bfab4addd141eeff41bd3a7fb14e13004a832cf7ef6" -dependencies = [ - "anyhow", - "glob", - "plist", - "schemars", - "serde", - "serde_json", - "tauri-utils", - "toml 0.8.2", - "walkdir", -] - -[[package]] -name = "tauri-plugin-clipboard-manager" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b7d556886c15849198c0948fd7f4c880492f0461539176da0a8a70272e2904" -dependencies = [ - "arboard", - "image", - "log", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror 1.0.64", -] - -[[package]] -name = "tauri-plugin-deep-link" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31a9b5725027c6e9e075b06cb2d5c2cd3b5c29daa8012b404e1ff755cc56082f" -dependencies = [ - "dunce", - "log", - "rust-ini", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "tauri-utils", - "thiserror 1.0.64", - "url", - "windows-registry 0.3.0", - "windows-result 0.2.0", -] - -[[package]] -name = "tauri-plugin-dialog" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddb2fe88b602461c118722c574e2775ab26a4e68886680583874b2f6520608b7" -dependencies = [ - "log", - "raw-window-handle", - "rfd", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "tauri-plugin-fs", - "thiserror 1.0.64", - "url", -] - -[[package]] -name = "tauri-plugin-fs" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab300488ebec3487ca5f56289692e7e45feb07eea8d5e1dba497f7dc9dd9c407" -dependencies = [ - "anyhow", - "dunce", - "glob", - "percent-encoding", - "schemars", - "serde", - "serde_json", - "serde_repr", - "tauri", - "tauri-plugin", - "thiserror 1.0.64", - "url", - "uuid 1.10.0", -] - -[[package]] -name = "tauri-plugin-shell" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "371fb9aca2823990a2d0db7970573be5fdf07881fcaa2b835b29631feb84aec1" -dependencies = [ - "encoding_rs", - "log", - "open", - "os_pipe", - "regex", - "schemars", - "serde", - "serde_json", - "shared_child", - "tauri", - "tauri-plugin", - "thiserror 1.0.64", - "tokio", -] - -[[package]] -name = "tauri-plugin-single-instance" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25ac834491d089699a2bc9266a662faf373c9f779f05a2235bc6e4d9e61769a" -dependencies = [ - "log", - "serde", - "serde_json", - "tauri", - "thiserror 1.0.64", - "windows-sys 0.59.0", - "zbus", -] - -[[package]] -name = "tauri-plugin-updater" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd3d2fe0f02bf52eebb5a9d23b987fffac6684646ab6fd683d706dafb18da87" -dependencies = [ - "base64 0.22.1", - "dirs 5.0.1", - "flate2", - "futures-util", - "http", - "infer", - "minisign-verify", - "percent-encoding", - "reqwest", - "semver", - "serde", - "serde_json", - "tar", - "tauri", - "tauri-plugin", - "tempfile", - "thiserror 1.0.64", - "time", - "tokio", - "url", - "windows-sys 0.59.0", - "zip", -] - -[[package]] -name = "tauri-plugin-window-state" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd1cef203a15b4772898e7bc8e57c1f34696e39848987dfcd294d51ba0525650" -dependencies = [ - "bitflags 2.6.0", - "log", - "serde", - "serde_json", - "tauri", - "tauri-plugin", - "thiserror 1.0.64", -] - [[package]] name = "tauri-runtime" version = "2.1.0" @@ -6752,17 +5365,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "tiff" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" -dependencies = [ - "flate2", - "jpeg-decoder", - "weezl", -] - [[package]] name = "time" version = "0.3.36" @@ -6794,15 +5396,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-keccak" -version = "2.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c9d3793400a45f954c52e73d068316d76b6f4e36977e3fcebb13a2721e80237" -dependencies = [ - "crunchy", -] - [[package]] name = "tinyvec" version = "1.8.0" @@ -6827,13 +5420,12 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio 1.0.2", + "mio", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "tracing", "windows-sys 0.52.0", ] @@ -7040,9 +5632,9 @@ version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c92af36a182b46206723bdf8a7942e20838cde1cf062e5b97854d57eb01763b" dependencies = [ - "core-graphics 0.24.0", + "core-graphics", "crossbeam-channel", - "dirs 5.0.1", + "dirs", "libappindicator", "muda", "objc2", @@ -7055,38 +5647,12 @@ dependencies = [ "windows-sys 0.59.0", ] -[[package]] -name = "trim-in-place" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "343e926fc669bc8cde4fa3129ab681c63671bae288b1f1081ceee6d9d37904fc" - [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "tungstenite" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" -dependencies = [ - "byteorder", - "bytes", - "data-encoding", - "http", - "httparse", - "log", - "rand 0.8.5", - "rustls", - "rustls-pki-types", - "sha1", - "thiserror 1.0.64", - "utf-8", -] - [[package]] name = "typeid" version = "1.0.2" @@ -7099,17 +5665,6 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" -[[package]] -name = "uds_windows" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89daebc3e6fd160ac4aa9fc8b3bf71e1f74fbf92367ae71fb83a037e8bf164b9" -dependencies = [ - "memoffset 0.9.1", - "tempfile", - "winapi", -] - [[package]] name = "unic-char-property" version = "0.9.0" @@ -7199,34 +5754,12 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" -[[package]] -name = "universal-hash" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" -dependencies = [ - "crypto-common", - "subtle", -] - [[package]] name = "untrusted" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" -[[package]] -name = "ureq" -version = "2.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" -dependencies = [ - "base64 0.22.1", - "log", - "once_cell", - "url", -] - [[package]] name = "url" version = "2.5.2" @@ -7257,6 +5790,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "uuid" version = "0.8.2" @@ -7276,17 +5815,6 @@ dependencies = [ "serde", ] -[[package]] -name = "v_frame" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" -dependencies = [ - "aligned-vec", - "num-traits", - "wasm-bindgen", -] - [[package]] name = "valuable" version = "0.1.0" @@ -7454,66 +5982,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "wayland-backend" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" -dependencies = [ - "cc", - "downcast-rs", - "rustix", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3f45d1222915ef1fd2057220c1d9d9624b7654443ea35c3877f7a52bd0a5a2d" -dependencies = [ - "bitflags 2.6.0", - "rustix", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b5755d77ae9040bb872a25026555ce4cb0ae75fd923e90d25fba07d81057de0" -dependencies = [ - "bitflags 2.6.0", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" -dependencies = [ - "proc-macro2", - "quick-xml 0.36.2", - "quote", -] - -[[package]] -name = "wayland-sys" -version = "0.31.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" -dependencies = [ - "dlib", - "log", - "pkg-config", -] - [[package]] name = "web-sys" version = "0.3.70" @@ -7524,24 +5992,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "webbrowser" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e5f07fb9bc8de2ddfe6b24a71a75430673fd679e568c48b52716cef1cfae923" -dependencies = [ - "block2", - "core-foundation 0.10.0", - "home", - "jni", - "log", - "ndk-context", - "objc2", - "objc2-foundation", - "url", - "web-sys", -] - [[package]] name = "webkit2gtk" version = "2.0.1" @@ -7631,12 +6081,6 @@ dependencies = [ "windows-core 0.58.0", ] -[[package]] -name = "weezl" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" - [[package]] name = "whoami" version = "1.5.2" @@ -7693,19 +6137,6 @@ dependencies = [ "windows-version", ] -[[package]] -name = "windows" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b97a83176b369b0eb2fd8158d4ae215357d02df9d40c1e1bf1879c5482c80" -dependencies = [ - "windows_aarch64_msvc 0.36.1", - "windows_i686_gnu 0.36.1", - "windows_i686_msvc 0.36.1", - "windows_x86_64_gnu 0.36.1", - "windows_x86_64_msvc 0.36.1", -] - [[package]] name = "windows" version = "0.57.0" @@ -7756,7 +6187,7 @@ dependencies = [ "windows-implement 0.58.0", "windows-interface 0.58.0", "windows-result 0.2.0", - "windows-strings 0.1.0", + "windows-strings", "windows-targets 0.52.6", ] @@ -7811,18 +6242,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ "windows-result 0.2.0", - "windows-strings 0.1.0", - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-registry" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bafa604f2104cf5ae2cc2db1dee84b7e6a5d11b05f737b60def0ffdc398cbc0a" -dependencies = [ - "windows-result 0.2.0", - "windows-strings 0.2.0", + "windows-strings", "windows-targets 0.52.6", ] @@ -7854,15 +6274,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "windows-strings" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978d65aedf914c664c510d9de43c8fd85ca745eaff1ed53edf409b479e441663" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -7972,12 +6383,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" -[[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -7996,12 +6401,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" -[[package]] -name = "windows_i686_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -8026,12 +6425,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" -[[package]] -name = "windows_i686_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -8050,12 +6443,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" -[[package]] -name = "windows_x86_64_gnu" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -8092,12 +6479,6 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" -[[package]] -name = "windows_x86_64_msvc" -version = "0.36.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -8177,6 +6558,15 @@ dependencies = [ "x11-dl", ] +[[package]] +name = "wyz" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +dependencies = [ + "tap", +] + [[package]] name = "x11" version = "2.21.0" @@ -8198,55 +6588,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" -dependencies = [ - "gethostname", - "rustix", - "x11rb-protocol", -] - -[[package]] -name = "x11rb-protocol" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" - -[[package]] -name = "x25519-dalek" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277" -dependencies = [ - "curve25519-dalek", - "rand_core 0.6.4", - "zeroize", -] - -[[package]] -name = "xattr" -version = "1.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da84f1a25939b27f6820d92aed108f83ff920fdf11a7b19366c27c4cda81d4f" -dependencies = [ - "libc", - "linux-raw-sys", - "rustix", -] - -[[package]] -name = "xdg-home" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec1cdab258fb55c0da61328dc52c8764709b249011b2cad0454c72f0bf10a1f6" -dependencies = [ - "libc", - "windows-sys 0.59.0", -] - [[package]] name = "xz2" version = "0.1.7" @@ -8257,69 +6598,10 @@ dependencies = [ ] [[package]] -name = "zbus" -version = "4.0.1" +name = "yansi" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b8e3d6ae3342792a6cc2340e4394334c7402f3d793b390d2c5494a4032b3030" -dependencies = [ - "async-broadcast", - "async-executor", - "async-fs", - "async-io", - "async-lock", - "async-process", - "async-recursion", - "async-task", - "async-trait", - "blocking", - "derivative", - "enumflags2", - "event-listener", - "futures-core", - "futures-sink", - "futures-util", - "hex", - "nix 0.27.1", - "ordered-stream", - "rand 0.8.5", - "serde", - "serde_repr", - "sha1", - "static_assertions", - "tokio", - "tracing", - "uds_windows", - "windows-sys 0.52.0", - "xdg-home", - "zbus_macros", - "zbus_names", - "zvariant", -] - -[[package]] -name = "zbus_macros" -version = "4.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7a3e850ff1e7217a3b7a07eba90d37fe9bb9e89a310f718afcde5885ca9b6d7" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "regex", - "syn 1.0.109", - "zvariant_utils", -] - -[[package]] -name = "zbus_names" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b9b1fef7d021261cc16cba64c351d291b715febe0fa10dc3a443ac5a5022e6c" -dependencies = [ - "serde", - "static_assertions", - "zvariant", -] +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "zerocopy" @@ -8348,7 +6630,6 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" dependencies = [ - "serde", "zeroize_derive", ] @@ -8372,7 +6653,7 @@ dependencies = [ "aes", "arbitrary", "bzip2", - "constant_time_eq 0.3.1", + "constant_time_eq", "crc32fast", "crossbeam-utils", "deflate64", @@ -8433,65 +6714,3 @@ dependencies = [ "cc", "pkg-config", ] - -[[package]] -name = "zune-core" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" - -[[package]] -name = "zune-inflate" -version = "0.2.54" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" -dependencies = [ - "simd-adler32", -] - -[[package]] -name = "zune-jpeg" -version = "0.4.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" -dependencies = [ - "zune-core", -] - -[[package]] -name = "zvariant" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e09e8be97d44eeab994d752f341e67b3b0d80512a8b315a0671d47232ef1b65" -dependencies = [ - "endi", - "enumflags2", - "serde", - "static_assertions", - "url", - "zvariant_derive", -] - -[[package]] -name = "zvariant_derive" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72a5857e2856435331636a9fbb415b09243df4521a267c5bedcd5289b4d5799e" -dependencies = [ - "proc-macro-crate 1.3.1", - "proc-macro2", - "quote", - "syn 1.0.109", - "zvariant_utils", -] - -[[package]] -name = "zvariant_utils" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bedb16a193cc12451873fee2a1bc6550225acece0e36f333e68326c73c8172" -dependencies = [ - "proc-macro2", - "quote", - "syn 1.0.109", -] diff --git a/Cargo.toml b/Cargo.toml index 1f30d19b..259b82d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,37 +1,32 @@ [workspace] resolver = "2" # virtual workspace resolver so we don't need a root package members = [ - "apps/testing", # onelauncher_test -- test the core crate in a cli setting - "apps/desktop", # onelauncher_gui -- the rust code for our tauri app - "packages/core", # onelauncher -- the rust core for onelauncher - "packages/core_new", - "packages/macros", # onelauncher_macros -- utility procedural macros for onelauncher - "packages/gamemode", # onelauncher_gamemode -- rust wrapper for feral gamemode - "packages/utils" # onelauncher_utils -- standard utilities for use within all crates + "packages/core", + "packages/entity", + "packages/gamemode", + "packages/macro", + "packages/migration", ] -[workspace.package] # sets default [package] settings for workspace members +[workspace.package] license = "GPL-3.0-only" -edition = "2021" # latest rust edition +edition = "2024" repository = "https://github.com/Polyfrost/OneLauncher" documentation = "https://docs.polyfrost.org/onelauncher" readme = "README.md" homepage = "https://polyfrost.org/projects/onelauncher" authors = [ "Polyfrost", "Polyfrost Contributors" ] -version = "0.1.0-alpha.2" # bump this manually for now +version = "0.2.0-alpha.2" [workspace.dependencies] -# # ============= WORKSPACE ============= # # -# best practice to define all workspace crates in the root -# even if they are not use, with no features enabled. -onelauncher = { path = "./packages/core" } -onelauncher_macros = { path = "./packages/macros" } -onelauncher_gui = { path = "./apps/desktop" } -onelauncher_test = { path = "./apps/testing" } +# workspace +onelauncher_core = { path = "./packages/core" } +onelauncher_entity = { path = "./packages/entity" } onelauncher_gamemode = { path = "./packages/gamemode" } -onelauncher_utils = { path = "./packages/utils" } +onelauncher_macro = { path = "./packages/macro" } +onelauncher_migration = { path = "./packages/migration" } -# # ============= TAURI ============= # # +# tauri tauri = { version = "2.0", features = [ "rustls-tls", "tracing", @@ -48,7 +43,10 @@ tauri-plugin-updater = { version = "2.0" } tauri-plugin-dialog = { version = "2.0" } tauri-plugin-deep-link = { version = "2.0" } -# # ============= CORE ============= # # +# core +interpulse = { version = "=1.2.2", features = [ "specta" ] } + +# code gen specta = { version = "2.0.0-rc.20", features = [ "chrono", "uuid", @@ -60,19 +58,18 @@ specta = { version = "2.0.0-rc.20", features = [ ] } tauri-specta = { version = "2.0.0-rc.20", features = [ "javascript", "typescript", "derive" ] } specta-typescript = { version = "=0.0.7" } -interpulse = { version = "=1.2.2", features = [ "specta" ] } -# # ============= SECURITY ============= # # +# security iota_stronghold = { version = "2.1" } zeroize = { version = "1.8", features = [ "zeroize_derive" ] } -# # ============= LOGGING ============= # # +# logging tracing = { version = "0.1" } tracing-subscriber = { version = "0.3", features = [ "chrono", "env-filter" ] } tracing-error = { version = "0.2" } tracing-appender = { version = "0.2" } -# # ============= SERIALIZATION ============= # # +# serialization & text serde = { version = "1.0", features = [ "derive" ] } serde_json = { version = "1.0" } serde_ini = { version = "0.2" } @@ -90,7 +87,7 @@ uuid = { version = "1.10", features = [ "serde", "v4" ] } toml = { version = "0.8" } nom = { version = "7.1" } -# # ============= NETWORK ============= # # +# network reqwest = { version = "0.12", default-features = false, features = [ "json", "stream", @@ -107,7 +104,7 @@ reqwest = { version = "0.12", default-features = false, features = [ async-tungstenite = { version = "0.28", features = [ "tokio-runtime", "tokio-rustls-webpki-roots" ] } webbrowser = { version = "1.0" } -# # ============= SYSTEM ============= # # +# io tokio = { version = "1.40", features = [ "full" ] } tokio-stream = { version = "0.1.16", features = [ "fs" ] } notify = { version = "6.1", default-features = false } @@ -119,49 +116,40 @@ dirs = { version = "5.0" } async_zip = { version = "0.0.17", features = [ "full" ] } async-compression = { version = "0.4.12", features = [ "flate2", "tokio" ] } flate2 = { version = "1.0" } +bytes = { version = "1.7" } + +# crypto sha1_smol = { version = "1.0", features = [ "std" ] } sha2 = { version = "0.10" } murmur2 = { version = "0.1.0" } md5 = { version = "0.7.0" } -bytes = { version = "1.7" } -# # ============= UTILITY ============= # # -sqlx = { version = "0.8", features = [ - "runtime-tokio", - "sqlite", +# db +sea-orm = { version = "1.1", features = [ + "sqlx-sqlite", + "runtime-tokio-rustls", "macros", - "derive", - "migrate", - "uuid", - "chrono" + "with-chrono", + "with-json", + "with-uuid" ] } +sea-orm-migration = { version = "1.1", features = [ "sqlx-sqlite", "runtime-tokio-rustls" ] } + +# utils thiserror = { version = "1.0" } anyhow = { version = "1.0" } -async-channel = { version = "2.3" } -mimalloc = { version = "0.1" } -pin-project-lite = { version = "0.2" } -once_cell = { version = "1.19" } -quote = { version = "1.0" } -syn = { version = "2.0", features = [ "full" ] } +sysinfo = { version = "0.31", features = [ "serde" ] } discord-rich-presence = { version = "0.2" } -winreg = { version = "0.52" } -paste = { version = "1.0" } -dashmap = { version = "6.1", features = [ "serde" ] } -lazy_static = { version = "1.5" } indicatif = { version = "0.17" } futures = { version = "0.3" } -async-recursion = { version = "1.1" } async-trait = { version = "0.1" } -sysinfo = { version = "0.31", features = [ "serde" ] } -sys-info = { version = "0.9" } whoami = { version = "1.5" } -cocoa = { version = "0.26" } -objc = { version = "0.2" } cc = { version = "1.1" } libc = { version = "0.2" } -dotenvy = { git = "https://github.com/allan2/dotenvy/", rev = "db0d6aa8fc8d1b0ddbfe94b5c833372e463eb1c5" } -# https://github.com/tauri-apps/tauri/blob/dev/crates/tauri/Cargo.toml#L102 -webkit2gtk = { version = "=2.0.1", features = [ "v2_40" ] } + +# macro +syn = { version = "2" } +quote = { version = "1" } [workspace.lints.clippy] all = { level = "warn", priority = -1 } @@ -197,10 +185,6 @@ deprecated = "warn" deprecated_in_future = "forbid" unused_must_use = "deny" -[patch.crates-io] -# rspc = { git = "https://github.com/oscartbeaumont/rspc", rev = "9f26d6400affdb501837cb023678268ad72feb9b" } -# rspc-tauri2 = { git = "https://github.com/specta-rs/tauri2", rev = "6b9419566e2a826fb2a62538c7647f4524ab0fea" } - [profile.dev] # add debug symbols/logic and optimize for reduced build time (parallel) debug = true # add debug info diff --git a/package.json b/package.json index f323620f..f1bbbe23 100644 --- a/package.json +++ b/package.json @@ -28,15 +28,17 @@ "test": "pnpm test:vi && pnpm --filter=./* run test", "format": "pnpm format:es && pnpm format:rs", "lint": "pnpm lint:es && pnpm lint:rs", + + "migrate": "sea-orm-cli migrate -d ./packages/migration", + "entity:gen": "sea-orm-cli generate entity -o packages/entity/src/entities --with-serde both --model-extra-attributes 'onelauncher_macro::specta'", + "frontend": "pnpm --filter @onelauncher/frontend -- ", "client": "pnpm --filter @onelauncher/client -- ", - "desktop": "pnpm --filter @onelauncher/desktop -- ", - "core_new": "pnpm --filter @onelauncher/core_new -- ", + "core": "pnpm --filter @onelauncher/core -- ", "scripts": "pnpm --filter @onelauncher/scripts -- ", - "testing": "pnpm --filter @onelauncher/testing --", "tauri": "pnpm desktop tauri-ext", + "postupdate": "cargo update", - "----------------------": "----------------------", "test:vi": "pnpm vitest run", "test:update": "pnpm vitest -u", "test:ui": "pnpm vitest --ui", diff --git a/packages/core/Cargo.toml b/packages/core/Cargo.toml index 64bc1edb..1262bbf1 100644 --- a/packages/core/Cargo.toml +++ b/packages/core/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "onelauncher" +name = "onelauncher_core" description = "The core of OneLauncher" version = { workspace = true } license = { workspace = true } @@ -10,67 +10,78 @@ readme = { workspace = true } homepage = { workspace = true } authors = { workspace = true } +[lib] +path = "src/lib.rs" + [features] -default = [] -# feature flag allowing us to interact with tauri (for loading animations, errors showing on gui, etc) -# also allows us to compile onelauncher core without tauri -tauri = [ "dep:tauri", "dep:tauri-specta", "specta" ] +default = [ "tauri" ] +tauri = [ + "dep:tauri", + "dep:tauri-specta", + "specta", + "gui" +] specta = [ "dep:specta" ] cli = [ "dep:indicatif" ] +gui = [] [lints] workspace = true [dependencies] -# features[default] -onelauncher_macros = { workspace = true } -onelauncher_utils = { workspace = true } +# core interpulse = { workspace = true } +onelauncher_migration = { workspace = true } +onelauncher_entity = { workspace = true } +onelauncher_macro = { workspace = true } + +# logging tracing = { workspace = true } tracing-subscriber = { workspace = true } tracing-error = { workspace = true } tracing-appender = { workspace = true } -notify = { workspace = true } -notify-debouncer-mini = { workspace = true } -iota_stronghold = { workspace = true } -zeroize = { workspace = true } -tokio = { workspace = true } + +# serialization serde = { workspace = true } serde_json = { workspace = true } serde_ini = { workspace = true } serde_repr = { workspace = true } serde_with = { workspace = true } -paste = { workspace = true } + +# utils +sea-orm = { workspace = true } +tokio = { workspace = true } +tokio-stream = { workspace = true } futures = { workspace = true } -zip = { workspace = true } uuid = { workspace = true } thiserror = { workspace = true } anyhow = { workspace = true } chrono = { workspace = true } reqwest = { workspace = true } -dirs = { workspace = true } +regex = { workspace = true } +sysinfo = { workspace = true } +whoami = { workspace = true } +rand = { workspace = true } +url = { workspace = true } +async-trait = { workspace = true } + +# integration +discord-rich-presence = { workspace = true } + +# crypto sha1_smol = { workspace = true } sha2 = { workspace = true } murmur2 = { workspace = true } md5 = { workspace = true } + +# io +zip = { workspace = true } async_zip = { workspace = true } -discord-rich-presence = { workspace = true } -regex = { workspace = true } -sysinfo = { workspace = true } -whoami = { workspace = true } -lazy_static = { workspace = true } -async-tungstenite = { workspace = true } -async-recursion = { workspace = true } -tokio-stream = { workspace = true } +dirs = { workspace = true } bytes = { workspace = true } -tempfile = { workspace = true } -rand = { workspace = true } -p256 = { workspace = true } -byteorder = { workspace = true } base64 = { workspace = true } -flate2 = { workspace = true } -toml = { workspace = true } -url = { workspace = true } +async-compression = { workspace = true } +dunce = { workspace = true } # features[tauri] tauri = { workspace = true, optional = true } @@ -82,11 +93,5 @@ specta = { workspace = true, optional = true } # features[cli] indicatif = { workspace = true, optional = true } -[build-dependencies] -dotenvy = { workspace = true } - -[target.'cfg(target_os = "windows")'.dependencies] -winreg = { workspace = true } - [target.'cfg(target_os = "linux")'.dependencies] onelauncher_gamemode = { workspace = true } diff --git a/packages/core/package.json b/packages/core/package.json index dde5a87f..8d195c16 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,14 +1,17 @@ { "name": "@onelauncher/core", - "version": "0.1.0-alpha.2", + "version": "0.2.0-alpha.1", "description": "Next-generation open source Minecraft launcher core", "license": "GPL-3.0-only", "repository": { "type": "git", "url": "git@github.com:polyfrost/onelauncher", - "directory": "packages/core" + "directory": "packages/core-new" }, "bugs": "https://github.com/polyfrost/onelauncher/issues", "sideEffects": false, - "scripts": {} + "scripts": { + "cargo": "cargo", + "binary": "cargo run --bin" + } } diff --git a/packages/core/src/api/ingress.rs b/packages/core/src/api/ingress.rs index 8ba5fd71..ebd02186 100644 --- a/packages/core/src/api/ingress.rs +++ b/packages/core/src/api/ingress.rs @@ -1,5 +1,56 @@ -use crate::store::{IngressProcessType, IngressProcessor}; +use crate::{store::{ingress::{IngressId, IngressType}, State}, LauncherResult}; -pub async fn check_ingress_feeds() -> crate::Result { - IngressProcessor::finished(IngressProcessType::IngressFeed).await +#[tracing::instrument] +pub async fn init_ingress( + ingress_type: IngressType, + message: &str, + total: f64, +) -> LauncherResult { + let state = State::get().await?; + let processor = &state.ingress_processor; + + let id = processor.create(ingress_type, message.to_string(), total).await?; + + Ok(id) } + +#[tracing::instrument] +pub async fn send_ingress(id: &IngressId, increment: f64) -> LauncherResult<()> { + let state = State::get().await?; + let processor = &state.ingress_processor; + + processor.send(id.0, increment).await?; + Ok(()) +} + +#[cfg(test)] +pub mod tests { + + #[cfg(feature = "cli")] + #[tokio::test] + pub async fn create_and_update_ingress() -> LauncherResult<()> { + assert!(cfg!(feature = "cli")); + + use std::time::Duration; + use crate::{api::{ingress::{init_ingress, send_ingress}, proxy::proxy_cli::ProxyCli}, initialize_core, store::ingress::IngressType, LauncherResult}; + + initialize_core(ProxyCli::new()).await?; + + let id = init_ingress(IngressType::Download { file_name: "Some-Mod-1.8.9.jar".into() }, "This is a test message", 100.0).await?; + tokio::time::sleep(Duration::from_millis(2350)).await; + + send_ingress(&id, 10.0).await?; + tokio::time::sleep(Duration::from_millis(2500)).await; + + send_ingress(&id, 20.0).await?; + tokio::time::sleep(Duration::from_millis(2500)).await; + + send_ingress(&id, 70.0).await?; + tokio::time::sleep(Duration::from_millis(2500)).await; + + drop(id); + + Ok(()) + } + +} \ No newline at end of file diff --git a/packages/core/src/api/mod.rs b/packages/core/src/api/mod.rs index b8653854..649515a3 100644 --- a/packages/core/src/api/mod.rs +++ b/packages/core/src/api/mod.rs @@ -1,31 +1,2 @@ -//! **`OneLauncher` API** -//! -//! API for interacting with our Rust core. - -pub mod cluster; -pub mod handler; pub mod ingress; -pub mod java; -pub mod metadata; -pub mod minecraft; -pub mod package; -pub mod processor; -pub mod proxy; -pub mod settings; - -pub mod data { - pub use crate::store::{ - ClusterMeta, Credentials, Directories, InitHooks, JavaOptions, Loader, ManagedDependency, - ManagedPackage, ManagedUser, ManagedVersion, Memory, MinecraftCredentials, PackageData, - PackageType, Resolution, Settings, - }; -} - -pub mod prelude { - pub use crate::cluster::{self, create, Cluster}; - pub use crate::data::*; - pub use crate::proxy::InternetPayload; - pub use crate::store::{ClusterPath, JavaVersions, PackageDependency, PackagePath}; - pub use crate::utils::java::JavaVersion; - pub use crate::{java, metadata, minecraft, package, processor, settings, State}; -} +pub mod proxy; \ No newline at end of file diff --git a/packages/core_new/src/api/proxy/message.rs b/packages/core/src/api/proxy/message.rs similarity index 88% rename from packages/core_new/src/api/proxy/message.rs rename to packages/core/src/api/proxy/message.rs index ce9d55d8..94af74a1 100644 --- a/packages/core_new/src/api/proxy/message.rs +++ b/packages/core/src/api/proxy/message.rs @@ -1,14 +1,13 @@ use serde::Serialize; -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] +#[onelauncher_macro::specta(with_event)] #[derive(Serialize, Debug, Clone)] pub struct MessagePayload { pub level: MessageLevel, pub message: String, } -#[cfg_attr(feature = "specta", derive(specta::Type))] +#[onelauncher_macro::specta] #[derive(Serialize, Debug, Clone)] pub enum MessageLevel { Info, diff --git a/packages/core/src/api/proxy/mod.rs b/packages/core/src/api/proxy/mod.rs index d8fb9bb4..f4cdffb2 100644 --- a/packages/core/src/api/proxy/mod.rs +++ b/packages/core/src/api/proxy/mod.rs @@ -1,277 +1,20 @@ -//! Proxy for Tauri/CLI specific features and communication -use serde::{Deserialize, Serialize}; -use std::collections::HashMap; -use std::path::PathBuf; -use std::sync::Arc; -use tokio::sync::{OnceCell, RwLock}; -use uuid::Uuid; +pub mod message; -use crate::store::{ClusterPath, IngressProcessor}; +#[cfg(feature = "tauri")] +pub mod proxy_tauri; -pub mod send; -pub mod utils; -pub use utils::*; +#[cfg(feature = "cli")] +pub mod proxy_cli; -static PROXY_STATE: OnceCell> = OnceCell::const_new(); -pub struct ProxyState { - #[cfg(feature = "tauri")] - pub app: tauri::AppHandle, - pub ingress_feeds: RwLock>, +#[async_trait::async_trait] +pub trait LauncherProxy: Send + Sync { + async fn send_ingress(&self, ingress: crate::store::ingress::IngressPayload) -> crate::LauncherResult<()>; + async fn send_message(&self, message: message::MessagePayload) -> crate::LauncherResult<()>; + + #[cfg(feature = "gui")] + fn hide_main_window(&self) -> crate::LauncherResult<()>; + + #[cfg(feature = "gui")] + fn show_main_window(&self) -> crate::LauncherResult<()>; } -#[derive(Serialize, Debug, Clone)] -pub struct Ingress { - pub ingress_uuid: Uuid, - pub message: String, - pub ingress_type: IngressType, - pub total: f64, - pub current: f64, - #[serde(skip)] - pub last_sent: f64, - #[cfg(feature = "cli")] - #[serde(skip)] - pub cli: indicatif::ProgressBar, -} - -#[derive(Serialize, Debug, Clone)] -pub struct IngressId(Uuid); - -impl Drop for IngressId { - #[clippy::has_significant_drop] - fn drop(&mut self) { - let ingress_uuid = self.0; - tokio::spawn(async move { - if let Ok(proxy_state) = ProxyState::get().await { - let mut ingress_feeds = proxy_state.ingress_feeds.write().await; - #[cfg(any(feature = "tauri", feature = "cli"))] - if let Some(ingress) = ingress_feeds.remove(&ingress_uuid) { - #[cfg(feature = "cli")] - { - let cli = ingress.cli; - cli.finish(); - } - - #[cfg(feature = "tauri")] - { - use tauri::Emitter; - let event = ingress.ingress_type.clone(); - let fraction = ingress.current / ingress.total; - - let _ = proxy_state.app.emit( - "ingress", - IngressPayload { - fraction: None, - message: "Complete".to_string(), - event, - ingress_uuid, - }, - ); - - tracing::trace!("exited at {fraction} for ingress: {:?}", ingress_uuid); - } - } - - #[cfg(not(any(feature = "tauri", feature = "cli")))] - ingress_feeds.remove(&ingress_uuid); - } - - if crate::State::initalized() { - let _ = IngressProcessor::finish( - crate::store::IngressProcessType::IngressFeed, - ingress_uuid, - ) - .await; - } - }); - } -} - -impl ProxyState { - #[cfg(feature = "tauri")] - pub async fn initialize(handle: &tauri::AppHandle) -> crate::Result> { - PROXY_STATE - .get_or_try_init(|| async { - Ok(Arc::new(Self { - app: handle.clone(), - ingress_feeds: RwLock::new(HashMap::new()), - })) - }) - .await - .cloned() - } - - #[cfg(not(feature = "tauri"))] - pub async fn initialize() -> crate::Result> { - PROXY_STATE - .get_or_try_init(|| async { - Ok(Arc::new(Self { - ingress_feeds: RwLock::new(HashMap::new()), - })) - }) - .await - .cloned() - } - - #[cfg(feature = "tauri")] - pub async fn get_main_window() -> crate::Result { - use tauri::Manager; - let value = Self::get().await?; - Ok(value.app.get_webview_window("main").unwrap()) - } - - #[allow(clippy::unused_async)] - #[cfg(feature = "tauri")] - pub async fn get() -> crate::Result> { - Ok(PROXY_STATE.get().ok_or(ProxyError::NotInitialized)?.clone()) - } - - #[cfg(not(feature = "tauri"))] - pub async fn get() -> crate::Result> { - Self::initialize().await - } - - pub async fn list_ingress_feeds() -> crate::Result> { - let value = Self::get().await?; - let read = value.ingress_feeds.read().await; - - let mut display_list: HashMap = HashMap::new(); - for (uuid, ingress) in read.iter() { - display_list.insert(*uuid, ingress.clone()); - } - - Ok(display_list) - } -} - -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Deserialize, Clone, Debug, Hash, PartialEq, Eq)] -#[serde(tag = "type")] -#[serde(rename_all = "snake_case")] -pub enum IngressType { - Initialize, - DownloadJava { - version: u32, - }, - DownloadLoader { - cluster_path: PathBuf, - cluster_name: String, - }, - SyncCluster { - cluster_path: PathBuf, - cluster_name: String, - }, - InferPackages, - CopyCluster { - import: PathBuf, - cluster_name: String, - }, - SyncConfig { - new_path: PathBuf, - }, - Archival { - cluster_path: PathBuf, - cluster_name: String, - }, - DownloadPackage { - cluster_path: PathBuf, - package_name: String, - icon: Option, - package_id: Option, - package_version: Option, - }, - DownloadPack { - cluster_path: PathBuf, - package_name: String, - icon: Option, - package_version: String, - }, -} - -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -pub struct IngressPayload { - pub event: IngressType, - pub ingress_uuid: Uuid, - pub fraction: Option, - pub message: String, -} - -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -pub struct OfflinePayload { - pub offline: bool, -} - -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -pub struct MessagePayload { - pub message: String, -} - -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -#[serde(tag = "event")] -pub enum InternetPayload { - InstallPackage { id: String }, - InstallPack { id: String }, - InstallPath { path: PathBuf }, -} - -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -pub struct ProcessPayload { - pub uuid: Uuid, - pub pid: u32, - pub event: ProcessPayloadType, - pub message: String, -} - -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone, Debug)] -#[serde(rename_all = "snake_case")] -pub enum ProcessPayloadType { - Started, - Modified, - Finished, - Logging, -} - -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -pub struct ClusterPayload { - pub uuid: Uuid, - pub cluster_path: ClusterPath, - pub path: PathBuf, - pub name: String, - pub event: ClusterPayloadType, -} - -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Serialize, Clone)] -#[serde(rename_all = "snake_case")] -pub enum ClusterPayloadType { - Created, - Inserted, - Synced, - Edited, - Deleted, -} - -#[derive(Debug, thiserror::Error)] -pub enum ProxyError { - #[error("event state was not initialized!")] - NotInitialized, - - #[error("non-existant ingress of key: {0}")] - NoIngressFound(Uuid), - - #[cfg(feature = "tauri")] - #[error("Tauri error: {0}")] - TauriError(#[from] tauri::Error), -} diff --git a/packages/core_new/src/api/proxy/proxy_cli.rs b/packages/core/src/api/proxy/proxy_cli.rs similarity index 100% rename from packages/core_new/src/api/proxy/proxy_cli.rs rename to packages/core/src/api/proxy/proxy_cli.rs diff --git a/packages/core_new/src/api/proxy/proxy_tauri.rs b/packages/core/src/api/proxy/proxy_tauri.rs similarity index 100% rename from packages/core_new/src/api/proxy/proxy_tauri.rs rename to packages/core/src/api/proxy/proxy_tauri.rs diff --git a/packages/core_new/src/bin/dirs.rs b/packages/core/src/bin/dirs.rs similarity index 89% rename from packages/core_new/src/bin/dirs.rs rename to packages/core/src/bin/dirs.rs index fa5ee4de..4244e376 100644 --- a/packages/core_new/src/bin/dirs.rs +++ b/packages/core/src/bin/dirs.rs @@ -1,4 +1,4 @@ -use onelauncher_new::store::Dirs; +use onelauncher_core::store::Dirs; #[tokio::main] async fn main() { diff --git a/packages/core/src/constants.rs b/packages/core/src/constants.rs index 515cf5f5..20b17852 100644 --- a/packages/core/src/constants.rs +++ b/packages/core/src/constants.rs @@ -1,11 +1,14 @@ //! **`OneLauncher` Constants** //! //! Public constant variables and strings that are used throughout the launcher. -//! Can be shared publically, any secrets should be stored in [`crate::store::credentials`]. // =========== Core Metadata =========== /// The name of the launcher. -pub const NAME: &str = "OneLauncher"; +pub const NAME: &str = match option_env!("LAUNCHER_NAME") { + Some(name) => name, + None => "OneLauncher", +}; + /// The version of the launcher (from `../Cargo.toml` env). pub const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -38,7 +41,7 @@ pub const MODRINTH_API_URL: &str = "https://api.modrinth.com/v2"; pub const MODRINTH_V3_API_URL: &str = "https://api.modrinth.com/v3"; /// The Curseforge API base url. pub const CURSEFORGE_API_URL: &str = "https://api.curseforge.com"; -/// The Curseforge API key. Reserved for use in OneLauncher projects only. Do not use in other projects without permission from the OneLauncher team. +/// The Curseforge API key. Reserved for use in Polyfrost projects only. Do not use in other projects without permission from the Polyfrost team. pub const CURSEFORGE_API_KEY: &str = "$2a$10$6utA1UNSmFPrE/Lh7b7ndeeGmiOkjKNY8kpFB0fsmE/d42ZAfFgCe"; /// The Minecraft game ID on Curseforge. pub const CURSEFORGE_GAME_ID: u32 = 432; @@ -48,7 +51,7 @@ pub const METADATA_API_URL: &str = "https://meta.polyfrost.org"; pub const FEATURED_PACKAGES_URL: &str = "https://polyfrost.org/meta/onelauncher/featured.json"; /// / API base url. pub const MCLOGS_API_URL: &str = "https://api.mclo.gs/1"; -/// https://skyclient.co/ metadata base url. +/// metadata base url. pub const SKYCLIENT_BASE_URL: &str = "https://raw.githubusercontent.com/SkyblockClient/SkyblockClient-REPO/refs/heads/main/v1"; // =========== Paths =========== @@ -56,10 +59,6 @@ pub const SKYCLIENT_BASE_URL: &str = "https://raw.githubusercontent.com/Skyblock /// /// [`Settings`]: crate::store::Settings pub const SETTINGS_FILE: &str = "settings.json"; -/// The public `cluster.json` file used to store the global [`Clusters`] state. -/// -/// [`Clusters`]: crate::store::Clusters -pub const CLUSTER_FILE: &str = "cluster.json"; /// The public `authentication.json` file used to store the global [`MinecraftAuth`] state. /// /// [`MinecraftAuth`]: crate::store::MinecraftAuth @@ -75,15 +74,6 @@ pub const PROCESSOR_FILE: &str = "processor.json"; /// [`Settings`]: crate::store::Settings pub const CURRENT_SETTINGS_FORMAT_VERSION: u32 = 1; -/// The constant core caches folder. -pub const CACHES_FOLDER: &str = "caches"; -/// The constant core crash reports folder. -pub const CRASH_PATH: &str = "crash-reports"; -/// The constant core clusters folder. -pub const CLUSTERS_FOLDER: &str = "clusters"; -/// The constant core metadata folder. -pub const METADATA_FOLDER: &str = "metadata"; - // =========== Hacky Mojang-spec OS constants =========== #[cfg(target_os = "windows")] pub const TARGET_OS: &str = "windows"; diff --git a/packages/core/src/error.rs b/packages/core/src/error.rs index b701b997..7577a7b9 100644 --- a/packages/core/src/error.rs +++ b/packages/core/src/error.rs @@ -1,180 +1,22 @@ -//! **`OneLauncher` Errors** -//! -//! Public wrappers around common `OneLauncher` errors. - -use tracing_error::InstrumentError; - -/// A standardized [`thiserror::Error`] type that is used across the launcher #[derive(thiserror::Error, Debug)] -pub enum ErrorKind { - /// Wrapper around [`tokio::sync::AcquireError`] to handle sempahore errors. - #[error("failed to acquire a tokio semaphore: {0}")] - AcquireError(#[from] tokio::sync::AcquireError), +pub enum LauncherError { + #[error(transparent)] + DirError(#[from] crate::store::DirectoryError), + #[error(transparent)] + IOError(#[from] crate::utils::io::IOError), + #[error(transparent)] + IngressError(#[from] crate::store::ingress::IngressError), - /// Wrapper around [`tokio::sync::oneshot::error::RecvError`] to handle recieve errors. - #[error("failed to handle async reciever: {0}")] - RecvError(#[from] tokio::sync::oneshot::error::RecvError), - - /// Wrapper around [`tokio::task::JoinError`] to handle tokio join handle errors. - #[error("failed to handle an async task: {0}")] - JoinError(#[from] tokio::task::JoinError), - - /// Wrapper around [`flate2::CompressError`] to handle flate compression errors. - #[error("failed to compress a file with flate: {0}")] - FlateError(#[from] flate2::CompressError), - - /// Wrapper around [`flate2::DecompressError`] to handle flate decompression errors. - #[error("failed to decompress a file with flate: {0}")] - DeflateError(#[from] flate2::DecompressError), - - /// Wrapper around [`uuid::Error`] to handle UUID parsing errors. - #[error("failed to parse and handle uuids: {0}")] - UUIDError(#[from] uuid::Error), - - /// Wrapper around [`interpulse::Error`] to handle interpulse errors. - #[error("failed to parse and handle metadata: {0}")] - MetadataError(#[from] interpulse::Error), - - /// Wrapper around [`serde_json::Error`] to handle Serde JSON parsing errors. - #[error("failed to manage serialization of json: {0}")] + #[error(transparent)] SerdeError(#[from] serde_json::Error), - - /// Wrapper around [`serde_ini::de::Error`] to handle Serde INI parsing errors. - #[error("failed to manage deserialization of ini: {0}")] - INIError(#[from] serde_ini::de::Error), - - /// Wrapper around [`reqwest::Error`] to handle HTTP errors. - #[error("failed to establish an http connection: {0}")] - HTTPError(#[from] reqwest::Error), - - /// Wrapper around [`zip::result::ZipError`] to handle zip errors. - #[error("failed to manage zip files: {0}")] - ZipError(#[from] zip::result::ZipError), - - /// Wrapper around [`async_zip::error::ZipError`] to handle async zip errors. - #[error("failed to manage zip files asynchronously: {0}")] - AsyncZipError(#[from] async_zip::error::ZipError), - - /// Wrapper around [`anyhow::Error`] to handle generic errors. #[error(transparent)] AnyhowError(#[from] anyhow::Error), + #[error(transparent)] + DbError(#[from] sea_orm::DbErr), - /// Wrapper around [`chrono::ParseError`] to handle date parsing errors. - #[error("failed to parse and handle datetime: {0}")] - ChronoError(#[from] chrono::ParseError), - - /// Wrapper around [`crate::state::DirectoryError`] to handle directory errors. - #[error("failed to get directory: {0}")] - DirectoryError(#[from] crate::store::DirectoryError), - - /// Wrapper around [`crate::api::proxy::ProxyError`] to handle ingress errors. - #[error("failed to handle api communication: {0}")] - ProxyError(#[from] crate::api::proxy::ProxyError), - - /// Wrapper around [`crate::store::MinecraftAuthError`] to handle Minecraft auth errors. - #[error("failed to authenticate with microsoft: {0}")] - AuthError(#[from] crate::store::MinecraftAuthError), - - /// Wrapper around [`crate::api::cluster::create::CreateClusterError`] to handle Cluster creation errors. - #[error("failed to create clusters: {0}")] - CreateClusterError(#[from] crate::api::cluster::create::CreateClusterError), - - /// Wrapper around [`notify:Error`] to handle file watching errors. - #[error("failed to watch file {0}")] - NotifyError(#[from] notify::Error), - - /// Wrapper around [`regex::Error`] to handle `RegExp` errors. - #[error("string verification with regex failed: {0}")] - RegexError(#[from] regex::Error), - - /// Wrapper around [`reqwest::header::ToStrError`] to handle header conversion errors. - #[error("failed to convert header to string: {0}")] - HeaderToStrError(#[from] reqwest::header::ToStrError), - - /// Wrapper around [`async_tungstenite::tungstenite::Error`] to handle WebSocket errors. - #[error("failed to handle websocket connection: {0}")] - WebSocketError(#[from] async_tungstenite::tungstenite::Error), - - /// Indicates an error with SHA checksum. - #[error("checksum {0} did not match {1}!")] - HashError(String, String), - - /// Wrapper around [`onelauncher_utils::io::IOError`] to handle wrapped `std::io` errors. - #[error("error handling IO operations: {0}")] - IOError(#[from] onelauncher_utils::io::IOError), - - /// Wrapper around [`std::io::Error`] to handle non-wrapped `std::io` errors. - #[error("error handling standard IO operations: {0}")] - StdIOError(#[from] std::io::Error), - - /// Wrapper around [`crate::utils::java::JavaError`] to handle java errors. - #[error("failed to manage java installations: {0}")] - JavaError(#[from] crate::utils::java::JavaError), - - /// Wrapper around [`crate::store::StrongholdError`] to handle stronghold errors. - #[error("failed to manage credentials with IOTA stronghold: {0}")] - StrongholdError(#[from] crate::store::StrongholdError), - - /// Wrapper around [`url::ParseError`] to handle URL parsing errors - #[error("failed to parse and handle URLs: {0}")] - URLError(#[from] url::ParseError), - - /// Wrapper around [`tauri::Error`] to handle Tauri errors when the feature flag is enabled #[cfg(feature = "tauri")] - #[error("error handling tauri: {0}")] + #[error(transparent)] TauriError(#[from] tauri::Error), } -/// A safe, accessible error structure wrapper around [`ErrorKind`] for use with [`tracing_error`]. -#[derive(Debug)] -pub struct Error { - /// The raw, inner [`ErrorKind`], wrapped in an [`Arc`]. - pub raw: std::sync::Arc, - /// The traced [`ErrorKind`] ([`tracing_error`]) to be parsed and logged. - pub source: tracing_error::TracedError>, -} - -impl From for String { - /// Converts an [`Error`] into a [`String`] value. - fn from(value: Error) -> Self { - value.to_string() - } -} - -impl std::error::Error for Error { - /// Get the source for the inner traced [`Error`]. - fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - self.source.source() - } -} - -impl std::fmt::Display for Error { - /// Format the [`Error`] and output it into the formatter buffer. - fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(fmt, "{}", self.source) - } -} - -impl> From for Error { - /// Converts an [`ErrorKind`] error into a traced [`Error`]. - /// Useful for reducing error mapping and standardizing error types. - fn from(source: E) -> Self { - let error = Into::::into(source); - let boxed_error = std::sync::Arc::new(error); - - Self { - raw: boxed_error.clone(), - source: boxed_error.in_current_span(), - } - } -} - -impl ErrorKind { - /// Converts the current [`ErrorKind`] into a traced [`Error`]. - pub fn as_error(self) -> Error { - self.into() - } -} - -/// Alias for a [`core::result::Result`] with the error type [`Error`]. -pub type Result = anyhow::Result; +pub type LauncherResult = Result; \ No newline at end of file diff --git a/packages/core/src/lib.rs b/packages/core/src/lib.rs index 485488a9..8b8d5ce8 100644 --- a/packages/core/src/lib.rs +++ b/packages/core/src/lib.rs @@ -1,20 +1,25 @@ -#![allow(clippy::all)] -//! # `OneLauncher` -//! -//! A library used as a core for our launcher and Rust APIs. +use api::proxy::LauncherProxy; +use store::{proxy::ProxyState, Dirs, State}; +use error::LauncherResult; +use logger::start_logger; -#[macro_use] -pub mod utils; - -pub mod api; pub mod constants; -pub mod error; -pub mod game; -pub mod logger; +pub mod utils; pub mod store; +pub mod api; +pub mod error; -pub use api::proxy::{Ingress, IngressType, ProxyState}; -pub use api::*; -pub use error::*; -pub use logger::start_logger; -pub use store::{InnerPathLinux, State}; +mod logger; + +pub use onelauncher_entity as entity; +pub use onelauncher_migration as migration; + +pub async fn initialize_core(proxy_backend: impl LauncherProxy + 'static) -> LauncherResult<()> { + Dirs::get().await?; + start_logger().await; + + ProxyState::initialize(proxy_backend).await?; + State::get().await?; + + Ok(()) +} \ No newline at end of file diff --git a/packages/core/src/logger.rs b/packages/core/src/logger.rs index 742a37ca..8a626188 100644 --- a/packages/core/src/logger.rs +++ b/packages/core/src/logger.rs @@ -1,74 +1,72 @@ -//! **`OneLauncher` Logger** -//! -//! Public utilities for [`tracing`] logging in `OneLauncher`. -//! -//! - `RUST_LOG=xxx` is a variable which defines tracing configuration (`ERROR > WARN > INFO > DEBUG > TRACE`) -//! - `RUST_LOG="onelauncher=trace"` will show **all** mesages from `OneLauncher` and not other dependencies. -//! - `RUST_LOG="info"` will show info, warn, and error logs. -//! -//! Errors returned to [`tauri`] are displayed as tracing error logs. -//! These errors also include an attached span trace if the error is from a [`tracing_error`] and the level is info, debug, or trace. -//! Tracing errors also provide Sentry metadata to be handled. -//! To set the environment variable on `unix` you can use the following command: `RUST_LOG="xxx" {your command}` -//! -//! The default `RUST_LOG` is `onelauncher=show`, meaning only logs from `OneLauncher` will be displayed at the info, warn, and error levels. - -use tracing_appender::non_blocking::WorkerGuard; - -// TODO: refactor logging and add more env filters. - -/// Initialize the global [`tracing`] logger in development. +// Handling for the live development logging +// This will log to the console, and will not log to a file #[cfg(debug_assertions)] -#[must_use] -pub fn start_logger() -> Option { - use tracing_subscriber::prelude::*; +pub async fn start_logger() { + use tracing_subscriber::{prelude::*, util::SubscriberInitExt}; - let filter = tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { - tracing_subscriber::EnvFilter::new("onelauncher=info,onelauncher_gui=info") - }); + let filter = tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(format!("{}=info", env!("CARGO_PKG_NAME")))); - let subscriber = tracing_subscriber::registry() - .with(tracing_subscriber::fmt::layer()) - .with(filter) - .with(tracing_error::ErrorLayer::default()); - - tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); - - None -} - -/// Initialize the global [`tracing`] logger in production. -#[cfg(not(debug_assertions))] -pub fn start_logger() -> Option { - use crate::store::Directories; - use tracing_appender::rolling::{RollingFileAppender, Rotation}; - use tracing_subscriber::fmt::time::ChronoLocal; - use tracing_subscriber::prelude::*; - - let logs_dir = if let Some(directory) = Directories::logs_dir() { - directory - } else { - eprintln!("failed to start logger"); - return None; - }; - - let filter = tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("onelauncher=info")); - - let file_appender = RollingFileAppender::new(Rotation::DAILY, logs_dir, "onelauncher.log"); - let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); - - let subscriber = tracing_subscriber::registry() - .with( + tracing_subscriber::registry() + .with( tracing_subscriber::fmt::layer() - .with_writer(non_blocking) - .with_ansi(false) - .with_timer(ChronoLocal::rfc_3339()), + .with_ansi(true) + .with_file(true) + .with_line_number(true) + .with_level(true) + .with_thread_names(true) + .pretty() ) - .with(filter) - .with(tracing_error::ErrorLayer::default()); - - tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); - - Some(guard) + .with(filter) + .with(tracing_error::ErrorLayer::default()) + .init(); +} + +// Handling for the live production logging +// This will log to a file in the logs directory, and will not show any logs in the console +#[cfg(not(debug_assertions))] +pub async fn start_logger() { + use chrono::Local; + use std::fs::OpenOptions; + use tracing_subscriber::fmt::time::ChronoLocal; + use tracing_subscriber::prelude::*; + + use crate::io::Dirs; + + // Initialize and get logs directory path + let logs_dir = Dirs::get().await?.launcher_logs_dir(); + + let log_file_name = format!("launcher_{}.log", Local::now().format("%Y%m%d_%H%M%S")); + let log_file_path = logs_dir.join(log_file_name); + + if let Err(err) = std::fs::create_dir_all(&logs_dir) { + eprintln!("Could not create logs directory: {err}"); + } + + let file = match OpenOptions::new() + .create(true) + .append(true) + .open(&log_file_path) + { + Ok(file) => file, + Err(e) => { + eprintln!("Could not start open log file: {e}"); + return None; + } + }; + + let filter = tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(format!("{}=info", env!("CARGO_PKG_NAME")))); + + tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .compact() + .with_writer(file) + .with_ansi(false) + .with_timer(ChronoLocal::rfc_3339()), + ) + .with(filter) + .with(tracing_error::ErrorLayer::default()) + .init(); } diff --git a/packages/core/src/store/db.rs b/packages/core/src/store/db.rs new file mode 100644 index 00000000..37a896d6 --- /dev/null +++ b/packages/core/src/store/db.rs @@ -0,0 +1,30 @@ +use std::{path::PathBuf, time::Duration}; + +use sea_orm::{ConnectOptions, Database, DatabaseConnection}; + +use crate::{utils::io::IOError, LauncherResult}; + +use super::Dirs; + +pub async fn create_pool_from_path(path: PathBuf) -> LauncherResult { + if !path.is_absolute() { + return Err(IOError::InvalidAbsolutePath(path).into()); + } + + let address = format!("sqlite:/{}?mode=rwc", path.to_string_lossy()); + let mut opts = ConnectOptions::new(address); + opts.min_connections(5) + .max_connections(40) + .connect_timeout(Duration::from_secs(5)) + .idle_timeout(Duration::from_secs(6 * 60 * 60 /* 6 hours */)); + + let db = Database::connect(opts).await?; + + Ok(db) +} + +#[tracing::instrument] +pub async fn create_pool() -> LauncherResult { + let path = Dirs::get().await?.db_file(); + create_pool_from_path(path).await +} \ No newline at end of file diff --git a/packages/core/src/store/dirs.rs b/packages/core/src/store/dirs.rs index 8eab75de..43d089ac 100644 --- a/packages/core/src/store/dirs.rs +++ b/packages/core/src/store/dirs.rs @@ -1,191 +1,96 @@ -//! Handles core directory management use std::path::PathBuf; -use tokio::sync::RwLock; -use super::Settings; -use crate::constants; +use tokio::sync::OnceCell; -/// Directory management and utilities. -#[derive(Debug)] -pub struct Directories { - /// Settings: All small caches and the core settings.json - pub settings_dir: PathBuf, - /// Base Configuration: Clusters and all Assets (should be changable as a setting that can go across file systems) - /// By default this should be the same as the `settings_dir` - pub config_dir: RwLock, - /// The current working directory of the directory manager. - pub cwd: PathBuf, +use crate::{constants, utils, LauncherResult}; + +/// The static [`OnceCell>`] for storing the global directory state. +/// Should be initialized as soon as possible (preferably before logging) +static DIRS_GLOBAL: OnceCell = OnceCell::const_new(); + +pub struct Dirs { + base_dir: PathBuf, } -impl Directories { - /// Bootstrap the initial settings directory on first startup. - #[must_use] - pub fn init_settings_dir() -> Option { - Self::env_path("ONELAUNCHER_CONFIG") +impl Dirs { + pub async fn get() -> LauncherResult<&'static Self> { + DIRS_GLOBAL.get_or_try_init(async || { + Self::initialize() + }).await + } + + fn initialize() -> LauncherResult { + let base_dir = utils::io::env_path("LAUNCHER_DIR") .or_else(|| Some(dirs::data_dir()?.join(constants::NAME))) - } + .ok_or(DirectoryError::BaseDir)?; - /// Bootstrap the initial settings directory on first startup. - #[inline] - pub fn init_settings_file() -> crate::Result { - let settings_dir = Self::init_settings_dir().ok_or(DirectoryError::ConfigDir)?; - Ok(settings_dir.join("settings.json")) - } - - /// Initialize the core directory manager - #[tracing::instrument] - pub fn initalize(settings: &Settings) -> crate::Result { - let cwd = std::env::current_dir().map_err(DirectoryError::WorkingDir)?; - let settings_dir = Self::init_settings_dir().ok_or(DirectoryError::ConfigDir)?; - let config_dir = settings - .config_dir - .clone() - .ok_or(DirectoryError::ConfigDir)?; Ok(Self { - settings_dir, - config_dir: RwLock::new(config_dir), - cwd, + base_dir }) } + /// Get the base directory for the launcher. + #[must_use] + pub const fn base_dir(&self) -> &PathBuf { + &self.base_dir + } + + /// Get the launcher's logs directory. + #[must_use] + pub fn launcher_logs_dir(&self) -> PathBuf { + self.base_dir().join("logs") + } + + + // --- FILES --- + + #[must_use] + pub fn db_file(&self) -> PathBuf { + self.base_dir().join("user_data.db") + } + + #[must_use] + pub fn settings_file(&self) -> PathBuf { + self.base_dir().join("settings.json") + } + + // --- GAME DIRECTORIES --- + /// Get the `config_dir/metadata` folder within the core config directory. #[inline] - pub async fn metadata_dir(&self) -> PathBuf { - self.config_dir - .read() - .await - .join(constants::METADATA_FOLDER) + #[must_use] + pub fn metadata_dir(&self) -> PathBuf { + self.base_dir().join("metadata") } /// Get the `config_dir/metadata/libraries` folder for Minecraft libraries. - #[inline] - pub async fn libraries_dir(&self) -> PathBuf { - self.metadata_dir().await.join("libraries") + #[must_use] + pub fn libraries_dir(&self) -> PathBuf { + self.metadata_dir().join("libraries") + } + + /// Get the `config_dir/metadata/natives` folder for Minecraft natives. + #[must_use] + pub fn natives_dir(&self) -> PathBuf { + self.metadata_dir().join("natives") } /// Get the `config_dir/metadata/java` directory. - #[inline] - pub async fn java_dir(&self) -> PathBuf { - self.metadata_dir().await.join("java_versions") + #[must_use] + pub fn java_dir(&self) -> PathBuf { + self.metadata_dir().join("java") } /// Get the `config_dir/metadata/caches` directory. - #[inline] - pub async fn caches_dir(&self) -> PathBuf { - self.metadata_dir().await.join("caches") - } - - /// Bootstrap the core logs directory and get it as a [`PathBuf`]. - #[inline] #[must_use] - pub fn logs_dir() -> Option { - Self::init_settings_dir().map(|d| d.join("logs")) - } - - /// Get the `settings_dir/settings.json` file as a [`PathBuf`]. - #[inline] - pub fn settings_file(&self) -> PathBuf { - self.settings_dir.join(constants::SETTINGS_FILE) - } - - /// Get a [`PathBuf`] from a provided environment variable. - #[inline] - fn env_path(name: &str) -> Option { - std::env::var_os(name).map(PathBuf::from) - } - - /// Get the `config_dir/metadata/assets` directory. - #[inline] - pub async fn assets_dir(&self) -> PathBuf { - self.metadata_dir().await.join("assets") - } - - /// Get the `config_dir/metadata/assets/indexes` directory. - #[inline] - pub async fn index_dir(&self) -> PathBuf { - self.assets_dir().await.join("indexes") - } - - /// Get the `config_dir/metadata/assets/objects` directory. - #[inline] - pub async fn objects_dir(&self) -> PathBuf { - self.assets_dir().await.join("objects") - } - - /// Get the `config_dir/metadata/assets/objects/{hash}` directory. - #[inline] - pub async fn object_dir(&self, hash: &str) -> PathBuf { - self.objects_dir().await.join(&hash[..2]).join(hash) - } - - /// Get the `config_dir/clusters` directory. - #[inline] - pub async fn clusters_dir(&self) -> PathBuf { - self.config_dir.read().await.join("clusters") - } - - /// Get the `config_dir/clusters/{uuid}` directory. - #[inline] - pub async fn cluster_dir(&self, uuid: uuid::Uuid) -> PathBuf { - self.clusters_dir().await.join(uuid.to_string()) - } - - /// Get the `{cluster_path}/logs` directory. - #[inline] - pub async fn cluster_logs_dir(cluster_path: &super::ClusterPath) -> crate::Result { - Ok(cluster_path.full_path().await?.join("logs")) - } - - /// Get the `{cluster_path}/crash_reports` directory. - #[inline] - pub async fn crash_reports_dir(cluster_path: &super::ClusterPath) -> crate::Result { - Ok(cluster_path.full_path().await?.join("crash-reports")) - } - - /// Get the `config_dir/metadata/resources` directory. - #[inline] - pub async fn legacy_assets_dir(&self) -> PathBuf { - self.metadata_dir().await.join("resources") - } - - /// Get the `config_dir/metadata/natives` directory. - #[inline] - pub async fn natives_dir(&self) -> PathBuf { - self.metadata_dir().await.join("natives") - } - - /// Get the `config_dir/metadata/natives/{version}` directory. - #[inline] - pub async fn version_natives_dir(&self, version: &str) -> PathBuf { - self.natives_dir().await.join(version) - } - - /// Get the Minecraft `config_dir/metadata/versions` directory. - #[inline] - pub async fn versions_dir(&self) -> PathBuf { - self.metadata_dir().await.join("versions") - } - - /// Get the Minecraft `config_dir/metadata/versions/{version}` directory. - #[inline] - pub async fn version_dir(&self, version: &str) -> PathBuf { - self.versions_dir().await.join(version) - } - - /// Get the `config_dir/icons` directory. - #[inline] - pub async fn icons_dir(&self) -> PathBuf { - self.config_dir.read().await.join("icons") + pub fn caches_dir(&self) -> PathBuf { + self.metadata_dir().join("caches") } } -/// Represents a core directory management error. #[derive(Debug, thiserror::Error)] pub enum DirectoryError { - /// An error for when a config directory cannot be initialized. - #[error("failed to get the user's config directory")] - ConfigDir, - /// A wrapper over [`std::io::Error`] for cwd fetching errors. - #[error("could not open working directory {0}")] - WorkingDir(std::io::Error), + #[error("Failed to get the base directory for the launcher.")] + BaseDir, } + diff --git a/packages/core_new/src/store/ingress.rs b/packages/core/src/store/ingress.rs similarity index 94% rename from packages/core_new/src/store/ingress.rs rename to packages/core/src/store/ingress.rs index 2ddc9202..12ec7339 100644 --- a/packages/core_new/src/store/ingress.rs +++ b/packages/core/src/store/ingress.rs @@ -93,8 +93,7 @@ pub struct Ingress { pub last_sent: f64, } -#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] -#[cfg_attr(feature = "specta", derive(specta::Type))] +#[onelauncher_macro::specta(with_event)] #[derive(Serialize, Debug, Clone)] pub struct IngressPayload { pub id: Uuid, @@ -104,7 +103,7 @@ pub struct IngressPayload { pub total: f64, } -#[cfg_attr(feature = "specta", derive(specta::Type))] +#[onelauncher_macro::specta] #[derive(Serialize, Debug, Clone)] pub enum IngressType { Download { diff --git a/packages/core/src/store/java.rs b/packages/core/src/store/java.rs new file mode 100644 index 00000000..2861e553 --- /dev/null +++ b/packages/core/src/store/java.rs @@ -0,0 +1,14 @@ +use serde::{Deserialize, Serialize}; + +use crate::LauncherResult; + +// pub async fn get_java_versions() -> LauncherResult> { +// // let java_versions = sqlx::query_as!( +// // JavaVersion, +// // r#" +// // SELECT id, major_version, display_name, absolute_path, full_version FROM java_versions +// // "# +// // ); + +// Ok(vec![]) +// } diff --git a/packages/core/src/store/mod.rs b/packages/core/src/store/mod.rs index 83e0772a..167e7de7 100644 --- a/packages/core/src/store/mod.rs +++ b/packages/core/src/store/mod.rs @@ -1,289 +1,11 @@ -//! **`OneLauncher` Store** -//! -//! Core state and storage management for the launcher, managing all states. - -use std::sync::Arc; -use std::time::Duration; - -use notify::RecommendedWatcher; -use notify_debouncer_mini::Debouncer; -use tokio::sync::{OnceCell, RwLock, Semaphore}; - -use crate::proxy::send::{init_ingress_internal, send_ingress, send_offline}; -use crate::utils::http; -use crate::utils::http::{FetchSemaphore, IoSemaphore}; - +pub(super) mod db; +pub mod ingress; +pub mod proxy; +pub mod java; mod dirs; -pub use self::dirs::*; - -mod minecraft; -pub use self::minecraft::*; - -mod credentials; -pub use self::credentials::*; - -mod discord; -pub use self::discord::*; - -mod metadata; -pub use self::metadata::*; - mod settings; -pub use self::settings::*; +mod state; -mod java_versions; -pub use self::java_versions::*; - -mod processor; -pub use self::processor::*; - -mod clusters; -pub use self::clusters::*; - -mod package; -pub use self::package::*; - -mod oneconfig; -pub use self::oneconfig::*; - -/// The static [`OnceCell>`] for storing the global runtime launcher state. -static LAUNCHER_STATE: OnceCell> = OnceCell::const_new(); - -/// The public `OneLauncher` state structure. -pub struct State { - /// Handles a boolean to check if the launcher is connected to the internet - pub offline: RwLock, - /// Handles core launcher directory and files - pub directories: Directories, - - /// Semaphore used to handle concurrent network requests - pub fetch_semaphore: FetchSemaphore, - /// Maximum number of semaphore permits to limit the amount of network requests at one time - pub fetch_semaphore_max: RwLock, - /// Semaphore used to handle concurrent IO requests - pub io_semaphore: IoSemaphore, - /// Maximum number of semaphore permits to limit the amount of IO requests at one time - pub io_semaphore_max: RwLock, - - /// Handles launcher metadata via [`interpulse`] - pub metadata: RwLock, - /// Handles launcher configuration and settings - pub settings: RwLock, - /// Handles minecraft auth flows and users - pub users: RwLock, - /// Handles processes - pub processor: RwLock, - /// Handles `OneConfig` integration with [`async-tungstenite`] - pub oneconfig: RwLock>, - /// Handles secure credential management with [`iota_stronghold`]. - pub credentials: RwLock>, - /// Handles clusters - pub(crate) clusters: RwLock, - /// Handles packages - pub(crate) packages: RwLock, - /// Handles internal ingress processes - pub(crate) ingress_processor: RwLock, - /// Handles file system watching for cluster manager - pub(crate) watcher: RwLock>, - /// Handles Discord rich prescence - pub discord_rpc: DiscordRPC, -} - -impl State { - /// Get the current global launcher state (or initialize it) - pub async fn get() -> crate::Result>> { - Ok(Arc::new( - LAUNCHER_STATE - .get_or_try_init(Self::initialize) - .await? - .read() - .await, - )) - } - - /// Get and lock writing to the current global launcher state (or initalize it) - pub async fn get_and_write() -> crate::Result> { - Ok(LAUNCHER_STATE - .get_or_try_init(Self::initialize) - .await? - .write() - .await) - } - - /// Initializes the core OneLauncher state fully. - #[tracing::instrument] - #[onelauncher_macros::memory] - async fn initialize() -> crate::Result> { - let ingress = - init_ingress_internal(crate::IngressType::Initialize, 100.0, "initializing state") - .await?; - - let settings = Settings::initialize(&Directories::init_settings_file()?).await?; - let directories = Directories::initalize(&settings)?; - send_ingress(&ingress, 10.0, None).await?; - let mut watcher = crate::utils::watcher::initialize_watcher()?; - let fetch_semaphore = - FetchSemaphore(RwLock::new(Semaphore::new(settings.max_async_fetches))); - let io_semaphore = IoSemaphore(RwLock::new(Semaphore::new( - settings.max_async_io_operations, - ))); - send_ingress(&ingress, 10.0, None).await?; - - let is_offline = !http::check_internet_connection(3).await; - - // TODO: Make this run in the background, this delays launcher startup by a couple seconds - let metadata_in = - Metadata::initialize(&directories, !is_offline, &io_semaphore, &fetch_semaphore); - let clusters_in = Clusters::initialize(&directories, &mut watcher); - let users_in = MinecraftState::initialize(&directories, &io_semaphore); - let (metadata, clusters, users) = crate::ingress_join! { - Some(&ingress), 70.0, Some("loading core"); - metadata_in, - clusters_in, - users_in, - }?; - - send_ingress(&ingress, 5.0, Some("loading packages")).await?; - let packages = Packages::initialize(&clusters); - - let ingress_processor = IngressProcessor::new(); - let discord_rpc = DiscordRPC::initialize(is_offline || settings.disable_discord)?; - if !settings.disable_discord && !is_offline { - let _ = discord_rpc.apply_activity("Idling...", true).await; - } - - let processor = Processor::new(); - - Self::status_loop(); - send_ingress(&ingress, 10.0, None).await?; - - Ok::, crate::Error>(RwLock::new(Self { - offline: RwLock::new(is_offline), - directories, - fetch_semaphore, - fetch_semaphore_max: RwLock::new(settings.max_async_fetches as u32), - io_semaphore, - io_semaphore_max: RwLock::new(settings.max_async_io_operations as u32), - metadata: RwLock::new(metadata), - settings: RwLock::new(settings), - users: RwLock::new(users), - processor: RwLock::new(processor), - oneconfig: RwLock::new(None), - credentials: RwLock::new(None), - clusters: RwLock::new(clusters), - packages: RwLock::new(packages), - ingress_processor: RwLock::new(ingress_processor), - watcher: RwLock::new(watcher), - discord_rpc, - })) - } - - /// Initalizes a "game loop" which checks for updates and if we are online. - pub fn status_loop() { - tokio::task::spawn(async { - loop { - let state = Self::get().await; - if let Ok(state) = state { - let _ = state.check_status().await; - } - - tokio::time::sleep(Duration::from_secs(10)).await; - } - }); - } - - /// Updates all data if we are connected to the internet. - pub fn update() { - tokio::task::spawn(async { - let state = Self::get(); - if let Ok(state) = state.await { - if !*state.offline.read().await { - let version_up = Clusters::update_versions(); - let meta_up = Metadata::update(); - let package_up = Clusters::update_packages(); - - let _ = tokio::join!(version_up, meta_up, package_up); - } - } - }); - } - - /// Synchronizes data that can change outside of our control. - #[tracing::instrument] - #[onelauncher_macros::memory] - pub async fn sync() -> crate::Result<()> { - let state = Self::get().await?; - let sync_settings = async { - let state = Arc::clone(&state); - tokio::spawn(async move { - let reader = state.settings.read().await; - reader.sync(&state.directories.settings_file()).await?; - Ok::<_, crate::Error>(()) - }) - .await? - }; - - let sync_clusters = async { - let state = Arc::clone(&state); - - tokio::spawn(async move { - let clusters = state.clusters.read().await; - - clusters.sync().await?; - Ok::<_, crate::Error>(()) - }) - .await? - }; - - tokio::try_join!(sync_settings, sync_clusters)?; - Ok(()) - } - - /// Resets the IO [`Semaphore`] to clear all tasks. - /// # This should ONLY be called when we can ensure - /// # that there are no current tasks running!! - pub async fn reset_io_semaphore(&self) { - let settings = self.settings.read().await; - let mut io_semaphore = self.io_semaphore.0.write().await; - let mut total_permits = self.io_semaphore_max.write().await; - // block ALL semaphore permits - this can be destructive - let _ = io_semaphore.acquire_many(*total_permits).await; - - io_semaphore.close(); - *total_permits = settings.max_async_io_operations as u32; - *io_semaphore = Semaphore::new(settings.max_async_io_operations); - } - - /// Resets the Fetch [`Semaphore`] to clear all tasks. - /// # This should ONLY be called when we can ensure - /// # that there are no current tasks running!! - pub async fn reset_fetch_semaphore(&self) { - let settings = self.settings.read().await; - let mut fetch_semaphore = self.fetch_semaphore.0.write().await; - let mut total_permits = self.fetch_semaphore_max.write().await; - // block ALL semaphore permits - this can be destructive - let _ = fetch_semaphore.acquire_many(*total_permits).await; - - fetch_semaphore.close(); - *total_permits = settings.max_async_io_operations as u32; - *fetch_semaphore = Semaphore::new(settings.max_async_fetches); - } - - /// Checks if we are online used in a loop. - pub async fn check_status(&self) -> crate::Result<()> { - let is_online = http::check_internet_connection(3).await; - let mut offline = self.offline.write().await; - if *offline != is_online { - return Ok(()); - } - - send_offline(!is_online).await?; - *offline = !is_online; - Ok(()) - } - - /// Determine if the global state is initalized or not (wrapper) - pub fn initalized() -> bool { - LAUNCHER_STATE.initialized() - } -} +pub use dirs::*; +pub use settings::*; +pub use state::*; \ No newline at end of file diff --git a/packages/core_new/src/store/proxy.rs b/packages/core/src/store/proxy.rs similarity index 100% rename from packages/core_new/src/store/proxy.rs rename to packages/core/src/store/proxy.rs diff --git a/packages/core/src/store/settings.rs b/packages/core/src/store/settings.rs index c51d0a65..52bb0ca8 100644 --- a/packages/core/src/store/settings.rs +++ b/packages/core/src/store/settings.rs @@ -1,209 +1,72 @@ -//! Handles user-inputted settings and global values - -use super::{Directories, JavaVersions}; -use crate::constants::CURRENT_SETTINGS_FORMAT_VERSION; -use onelauncher_utils::io; +use onelauncher_entity::setting_profiles; use serde::{Deserialize, Serialize}; -use std::path::{Path, PathBuf}; -/// A global settings state for the launcher. -#[cfg_attr(feature = "specta", derive(specta::Type))] +use crate::{send_warning, utils::io, LauncherResult}; + +use super::Dirs; + +#[onelauncher_macro::specta] #[derive(Debug, Serialize, Deserialize, Clone)] +#[serde(default)] pub struct Settings { - /// A `OneLauncher` theme managed by the `OneLauncher` GUI. - #[serde(default = "theme_default")] - pub theme: String, - /// A global browser list view for the `OneLauncher` GUI. - #[serde(default)] - pub browser_list_view: BrowserListView, - /// Does not ask for confirmation when closing the `OneLauncher` GUI - #[serde(default)] - pub hide_close_prompt: bool, - /// Disables animations in the `OneLauncher` GUI - #[serde(default)] - pub disable_animations: bool, - /// A global fullscreen Minecraft state. - #[serde(default)] - pub force_fullscreen: bool, - /// Whether to allow launching the same cluster under the same account. - #[serde(default)] + pub global_game_settings: setting_profiles::Model, pub allow_parallel_running_clusters: bool, - /// Whether to launch Feral Gamemode on Linux systems. - #[serde(default)] pub enable_gamemode: bool, - /// A global default [`Resolution`] for Minecraft. - pub resolution: Resolution, - /// A global [`JavaVersions`] list and default version. - pub java_versions: JavaVersions, - /// A global [`Memory`] settings store for Java memory settings. - pub memory: Memory, - /// Global and default initialization hooks . - pub init_hooks: InitHooks, - /// Global and default custom Java arguments. - pub custom_java_args: Vec, - /// Global and default custom environment variables. - pub custom_env_args: Vec<(String, String)>, - /// Global and default maximum [`Semaphore`] I/O operations. - pub max_async_io_operations: usize, - /// Global and default maximum [`Semaphore`] HTTP operations. - pub max_async_fetches: usize, - /// The [`CURRENT_FORMAT_VERSION`] of this settings file. - pub version: u32, - /// Whether or not to disable Discord IPC. - #[serde(default)] - pub disable_discord: bool, - /// Whether or not to enable a debug mode in the launcher. - #[serde(default)] - pub debug_mode: bool, - /// Whether or not to disable Plausible and Sentry analytics. - #[serde(default)] - pub disable_analytics: bool, - /// The core global config directory stored as a [`PathBuf`]. - #[serde(default = "Directories::init_settings_dir")] - pub config_dir: Option, - /// Whether or not to minimize the launcher upon a game launch. - #[serde(default)] - pub hide_on_launch: bool, - /// Enable/disable custom window decorations. - #[serde(default)] - pub custom_frame: bool, - /// Completed onboarding. - #[serde(default)] - pub onboarding_completed: bool, + pub discord_enabled: bool, + pub settings_version: u32, } -fn theme_default() -> String { - "dark".to_string() +impl Default for Settings { + fn default() -> Self { + Self { + global_game_settings: default_global_game_settings(), + allow_parallel_running_clusters: false, + discord_enabled: false, + enable_gamemode: false, + settings_version: 2, + } + } } impl Settings { - /// Initializes the global settings state. #[tracing::instrument] - pub async fn initialize(file: &Path) -> crate::Result { - let mut recovered_corruption = false; - - let settings = if file.exists() { - let read_settings = io::read(&file) - .await - .map_err(|err| anyhow::anyhow!("error reading settings file: {0}", err).into()) - .and_then(|it| serde_json::from_slice::(&it).map_err(crate::Error::from)); - - if let Err(ref err) = read_settings { - tracing::error!("failed to load settings file: {err}."); - let backup = file.with_extension("json.bak"); - tracing::error!( - "corrupted settings will be backed up as {}, and a new one will be created", - backup.display() - ); - let _ = io::rename(file, backup).await; - recovered_corruption = true; - } - - read_settings.ok() - } else { - None - }; - - if let Some(settings) = settings { - Ok(settings) - } else { - let settings = Self { - theme: "dark".to_string(), - browser_list_view: BrowserListView::Grid, - hide_close_prompt: true, - disable_animations: false, - force_fullscreen: false, - allow_parallel_running_clusters: false, - #[cfg(target_os = "linux")] - enable_gamemode: true, - #[cfg(not(target_os = "linux"))] - enable_gamemode: false, - resolution: Resolution::default(), - java_versions: JavaVersions::new(), - memory: Memory::default(), - init_hooks: InitHooks::default(), - custom_env_args: Vec::new(), - custom_java_args: Vec::new(), - max_async_fetches: 10, - max_async_io_operations: 10, - version: CURRENT_SETTINGS_FORMAT_VERSION, - disable_analytics: false, - disable_discord: false, - debug_mode: false, - config_dir: Directories::init_settings_dir(), - hide_on_launch: false, - custom_frame: true, - onboarding_completed: false, - }; - - if recovered_corruption { - settings.sync(file).await?; - } - - Ok(settings) + pub async fn new() -> Self { + match Self::read().await { + Ok(settings) => settings, + Err(err) => { + send_warning!("Failed to read settings file: {}", err); + Self::default() + }, } } - /// Synchronizes the current settings from a file. - #[tracing::instrument(skip(self))] - pub async fn sync(&self, to: &Path) -> crate::Result<()> { - io::write(to, serde_json::to_vec(self)?).await?; + async fn read() -> LauncherResult { + let path = Dirs::get().await?.settings_file(); + let data = io::read(path).await?; + Ok(serde_json::from_slice(&data)?) + } + + pub async fn save(&self) -> LauncherResult<()> { + let path = Dirs::get().await?.settings_file(); + let data = serde_json::to_string_pretty(self)?; + io::write(path, data).await?; + Ok(()) } } -/// `OneLauncher` browser list type. -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] -#[serde(rename_all = "snake_case")] -pub enum BrowserListView { - #[default] - Grid, - List, -} - -/// Global memory settings across all clusters. -#[derive(Serialize, Deserialize, Debug, Clone, Copy)] -#[cfg_attr(feature = "specta", derive(specta::Type))] -pub struct Memory { - /// Maximum amount of Java memory available globally. - pub maximum: u32, - /// Minimum amount of Java memory available globally. - pub minimum: u32, -} - -impl Default for Memory { - fn default() -> Self { - Self { - maximum: 2048, - minimum: 256, - } +fn default_global_game_settings() -> setting_profiles::Model { + setting_profiles::Model { + name: "Global".into(), + force_fullscreen: Some(false), + hook_post: None, + hook_pre: None, + hook_wrapper: None, + java_id: None, + launch_args: None, + launch_env: None, + mem_max: Some(3072), + res_h: None, + res_w: None, } -} - -/// Global Minecraft resolution. -#[derive(Serialize, Deserialize, Debug, Clone, Copy)] -#[cfg_attr(feature = "specta", derive(specta::Type))] -pub struct Resolution(pub u16, pub u16); - -impl Default for Resolution { - fn default() -> Self { - Self(854, 480) - } -} - -/// Global initialization hooks for all Minecraft clusters. -#[derive(Serialize, Deserialize, Debug, Clone, Default)] -#[serde(default)] -#[cfg_attr(feature = "specta", derive(specta::Type))] -pub struct InitHooks { - /// Pre-launch hook. - #[serde(skip_serializing_if = "Option::is_none")] - pub pre: Option, - /// Wrapper hook for the runtime of the game instance. - #[serde(skip_serializing_if = "Option::is_none")] - pub wrapper: Option, - /// Post-launch hook. - #[serde(skip_serializing_if = "Option::is_none")] - pub post: Option, -} +} \ No newline at end of file diff --git a/packages/core_new/src/store/state.rs b/packages/core/src/store/state.rs similarity index 95% rename from packages/core_new/src/store/state.rs rename to packages/core/src/store/state.rs index 12a99c86..2ec72bf7 100644 --- a/packages/core_new/src/store/state.rs +++ b/packages/core/src/store/state.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use sqlx::SqlitePool; +use sea_orm::DatabaseConnection; use tokio::sync::{OnceCell, RwLock}; use crate::LauncherResult; @@ -13,7 +13,7 @@ static LAUNCHER_STATE: OnceCell> = OnceCell::const_new(); pub struct State { pub ingress_processor: IngressProcessor, pub settings: Settings, - pub db: SqlitePool, + pub db: DatabaseConnection, } impl State { diff --git a/packages/core_new/src/utils/io.rs b/packages/core/src/utils/io.rs similarity index 97% rename from packages/core_new/src/utils/io.rs rename to packages/core/src/utils/io.rs index 3cd807c3..721662d9 100644 --- a/packages/core_new/src/utils/io.rs +++ b/packages/core/src/utils/io.rs @@ -4,17 +4,17 @@ use tokio::io::AsyncReadExt; /// A wrapper around generic and unhelpful [`std::io::Error`] messages. #[derive(Debug, thiserror::Error)] pub enum IOError { - /// A wrapped [`std::io::Error`] along with the path involved in the error. + #[error("invalid absolute path '{0}'")] + InvalidAbsolutePath(std::path::PathBuf), + #[error("error acessing path: {source}, path: {path}")] IOErrorWrapper { #[source] source: std::io::Error, path: String, }, - /// A wrapped [`zip::result::ZipError`]. #[error(transparent)] ZipError(#[from] zip::result::ZipError), - /// A wrapped [`std::io::Error`]. #[error(transparent)] IOError(#[from] std::io::Error), } diff --git a/packages/core/src/utils/mod.rs b/packages/core/src/utils/mod.rs index 85093225..678b90ea 100644 --- a/packages/core/src/utils/mod.rs +++ b/packages/core/src/utils/mod.rs @@ -1,15 +1 @@ -//! **`OneLauncher` Core Utilities** -//! Standard asynchronous utilities and wrappers for use within the launcher core. -//! -//! - [`http`]: Async extensions and wrappers around [`reqwest`] functions. -//! - [`java`]: Async utilities for managing and downloading Java versions. -//! - [`watcher`]: Async utilities for watching files with [`notify`]. - -pub mod http; -pub mod java; -pub mod pagination; -pub mod watcher; -pub mod crypto; - -#[cfg(feature = "tauri")] -pub mod window; +pub mod io; \ No newline at end of file diff --git a/packages/core_new/package.json b/packages/core_new/package.json deleted file mode 100644 index 016a37a4..00000000 --- a/packages/core_new/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "@onelauncher/core_new", - "version": "0.2.0-alpha.1", - "description": "Next-generation open source Minecraft launcher core", - "license": "GPL-3.0-only", - "repository": { - "type": "git", - "url": "git@github.com:polyfrost/onelauncher", - "directory": "packages/core-new" - }, - "bugs": "https://github.com/polyfrost/onelauncher/issues", - "sideEffects": false, - "scripts": { - "cargo": "cargo", - "binary": "cargo run --bin", - "sqlx": "sqlx" - } -} diff --git a/packages/core_new/sqlx_guide.md b/packages/core_new/sqlx_guide.md deleted file mode 100644 index 932d65b3..00000000 --- a/packages/core_new/sqlx_guide.md +++ /dev/null @@ -1,14 +0,0 @@ -# Connecting to database on *nix -```bash -export DATABASE_URL=sqlite:/path/to/user_data.db -``` - -# Connecting to database on Windows -```cmd -set DATABASE_URL=sqlite:C:\\path\\to\\user_data.db -``` - -# Connecting to database on Windows (PowerShell) -```powershell -$env:DATABASE_URL="sqlite:C:\\path\\to\\user_data.db" -``` diff --git a/packages/core_new/src/api/ingress.rs b/packages/core_new/src/api/ingress.rs deleted file mode 100644 index 0200b9b4..00000000 --- a/packages/core_new/src/api/ingress.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::{store::{ingress::{IngressId, IngressType}, State}, LauncherResult}; - -#[tracing::instrument] -pub async fn init_ingress( - ingress_type: IngressType, - message: &str, - total: f64, -) -> LauncherResult { - let state = State::get().await?; - let processor = &state.ingress_processor; - - let id = processor.create(ingress_type, message.to_string(), total).await?; - - Ok(id) -} - -#[tracing::instrument] -pub async fn send_ingress(id: &IngressId, increment: f64) -> LauncherResult<()> { - let state = State::get().await?; - let processor = &state.ingress_processor; - - processor.send(id.0, increment).await?; - Ok(()) -} - -#[cfg(test)] -pub mod tests { - use std::time::Duration; - - use crate::{api::{ingress::{init_ingress, send_ingress}, proxy::proxy_cli::ProxyCli}, initialize_core, store::ingress::IngressType, LauncherResult}; - - - #[tokio::test] - pub async fn create_and_update_ingress() -> LauncherResult<()> { - assert!(cfg!(feature = "cli")); - - initialize_core(ProxyCli::new()).await?; - - let id = init_ingress(IngressType::Download { file_name: "Some-Mod-1.8.9.jar".into() }, "This is a test message", 100.0).await?; - tokio::time::sleep(Duration::from_millis(2350)).await; - - send_ingress(&id, 10.0).await?; - tokio::time::sleep(Duration::from_millis(2500)).await; - - send_ingress(&id, 20.0).await?; - tokio::time::sleep(Duration::from_millis(2500)).await; - - send_ingress(&id, 70.0).await?; - tokio::time::sleep(Duration::from_millis(2500)).await; - - drop(id); - - Ok(()) - } - -} \ No newline at end of file diff --git a/packages/core_new/src/api/mod.rs b/packages/core_new/src/api/mod.rs deleted file mode 100644 index 649515a3..00000000 --- a/packages/core_new/src/api/mod.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod ingress; -pub mod proxy; \ No newline at end of file diff --git a/packages/core_new/src/api/proxy/mod.rs b/packages/core_new/src/api/proxy/mod.rs deleted file mode 100644 index f4cdffb2..00000000 --- a/packages/core_new/src/api/proxy/mod.rs +++ /dev/null @@ -1,20 +0,0 @@ -pub mod message; - -#[cfg(feature = "tauri")] -pub mod proxy_tauri; - -#[cfg(feature = "cli")] -pub mod proxy_cli; - -#[async_trait::async_trait] -pub trait LauncherProxy: Send + Sync { - async fn send_ingress(&self, ingress: crate::store::ingress::IngressPayload) -> crate::LauncherResult<()>; - async fn send_message(&self, message: message::MessagePayload) -> crate::LauncherResult<()>; - - #[cfg(feature = "gui")] - fn hide_main_window(&self) -> crate::LauncherResult<()>; - - #[cfg(feature = "gui")] - fn show_main_window(&self) -> crate::LauncherResult<()>; -} - diff --git a/packages/core_new/src/error.rs b/packages/core_new/src/error.rs deleted file mode 100644 index bf68aee2..00000000 --- a/packages/core_new/src/error.rs +++ /dev/null @@ -1,24 +0,0 @@ -#[derive(thiserror::Error, Debug)] -pub enum LauncherError { - #[error(transparent)] - DirError(#[from] crate::store::DirectoryError), - #[error(transparent)] - IOError(#[from] crate::utils::io::IOError), - #[error(transparent)] - IngressError(#[from] crate::store::ingress::IngressError), - - #[error(transparent)] - SerdeError(#[from] serde_json::Error), - #[error(transparent)] - DbError(#[from] sqlx::Error), - #[error(transparent)] - DbMigrationError(#[from] sqlx::migrate::MigrateError), - #[error(transparent)] - AnyhowError(#[from] anyhow::Error), - - #[cfg(feature = "tauri")] - #[error(transparent)] - TauriError(#[from] tauri::Error), -} - -pub type LauncherResult = Result; \ No newline at end of file diff --git a/packages/core_new/src/lib.rs b/packages/core_new/src/lib.rs deleted file mode 100644 index c8712c58..00000000 --- a/packages/core_new/src/lib.rs +++ /dev/null @@ -1,22 +0,0 @@ -pub mod constants; -pub mod utils; -pub mod store; -pub mod api; - -mod error; -mod logger; - -use api::proxy::LauncherProxy; -pub use error::{LauncherResult, LauncherError}; -pub use logger::start_logger; -use store::{proxy::ProxyState, Dirs, State}; - -pub async fn initialize_core(proxy_backend: impl LauncherProxy + 'static) -> LauncherResult<()> { - Dirs::get().await?; - start_logger().await; - - ProxyState::initialize(proxy_backend).await?; - State::get().await?; - - Ok(()) -} \ No newline at end of file diff --git a/packages/core_new/src/logger.rs b/packages/core_new/src/logger.rs deleted file mode 100644 index 8a626188..00000000 --- a/packages/core_new/src/logger.rs +++ /dev/null @@ -1,72 +0,0 @@ -// Handling for the live development logging -// This will log to the console, and will not log to a file -#[cfg(debug_assertions)] -pub async fn start_logger() { - use tracing_subscriber::{prelude::*, util::SubscriberInitExt}; - - let filter = tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(format!("{}=info", env!("CARGO_PKG_NAME")))); - - tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .with_ansi(true) - .with_file(true) - .with_line_number(true) - .with_level(true) - .with_thread_names(true) - .pretty() - ) - .with(filter) - .with(tracing_error::ErrorLayer::default()) - .init(); -} - -// Handling for the live production logging -// This will log to a file in the logs directory, and will not show any logs in the console -#[cfg(not(debug_assertions))] -pub async fn start_logger() { - use chrono::Local; - use std::fs::OpenOptions; - use tracing_subscriber::fmt::time::ChronoLocal; - use tracing_subscriber::prelude::*; - - use crate::io::Dirs; - - // Initialize and get logs directory path - let logs_dir = Dirs::get().await?.launcher_logs_dir(); - - let log_file_name = format!("launcher_{}.log", Local::now().format("%Y%m%d_%H%M%S")); - let log_file_path = logs_dir.join(log_file_name); - - if let Err(err) = std::fs::create_dir_all(&logs_dir) { - eprintln!("Could not create logs directory: {err}"); - } - - let file = match OpenOptions::new() - .create(true) - .append(true) - .open(&log_file_path) - { - Ok(file) => file, - Err(e) => { - eprintln!("Could not start open log file: {e}"); - return None; - } - }; - - let filter = tracing_subscriber::EnvFilter::try_from_default_env() - .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new(format!("{}=info", env!("CARGO_PKG_NAME")))); - - tracing_subscriber::registry() - .with( - tracing_subscriber::fmt::layer() - .compact() - .with_writer(file) - .with_ansi(false) - .with_timer(ChronoLocal::rfc_3339()), - ) - .with(filter) - .with(tracing_error::ErrorLayer::default()) - .init(); -} diff --git a/packages/core_new/src/store/db.rs b/packages/core_new/src/store/db.rs deleted file mode 100644 index 5ec565d3..00000000 --- a/packages/core_new/src/store/db.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::path::PathBuf; - -use chrono::Duration; -use sqlx::{migrate::MigrateDatabase, sqlite::SqlitePoolOptions, Sqlite, SqlitePool}; - -use crate::LauncherResult; - -use super::Dirs; - -pub async fn create_pool_from_path(path: PathBuf) -> LauncherResult { - let protocol = String::from("sqlite:"); - let connection_str = protocol + path.to_str().expect("invalid path used for sqlite connection"); - - if !Sqlite::database_exists(&connection_str).await? { - - Sqlite::create_database(&connection_str).await?; - } - - let pool = SqlitePoolOptions::new() - .max_connections(40) - .idle_timeout(Some(Duration::hours(6).to_std().unwrap())) - .connect(&connection_str).await?; - - sqlx::migrate!().run(&pool).await?; - - Ok(pool) -} - -#[tracing::instrument] -pub async fn create_pool() -> LauncherResult { - let path = Dirs::get().await?.db_file(); - create_pool_from_path(path).await -} \ No newline at end of file diff --git a/packages/core_new/src/store/dirs.rs b/packages/core_new/src/store/dirs.rs deleted file mode 100644 index 43d089ac..00000000 --- a/packages/core_new/src/store/dirs.rs +++ /dev/null @@ -1,96 +0,0 @@ -use std::path::PathBuf; - -use tokio::sync::OnceCell; - -use crate::{constants, utils, LauncherResult}; - -/// The static [`OnceCell>`] for storing the global directory state. -/// Should be initialized as soon as possible (preferably before logging) -static DIRS_GLOBAL: OnceCell = OnceCell::const_new(); - -pub struct Dirs { - base_dir: PathBuf, -} - -impl Dirs { - pub async fn get() -> LauncherResult<&'static Self> { - DIRS_GLOBAL.get_or_try_init(async || { - Self::initialize() - }).await - } - - fn initialize() -> LauncherResult { - let base_dir = utils::io::env_path("LAUNCHER_DIR") - .or_else(|| Some(dirs::data_dir()?.join(constants::NAME))) - .ok_or(DirectoryError::BaseDir)?; - - Ok(Self { - base_dir - }) - } - - /// Get the base directory for the launcher. - #[must_use] - pub const fn base_dir(&self) -> &PathBuf { - &self.base_dir - } - - /// Get the launcher's logs directory. - #[must_use] - pub fn launcher_logs_dir(&self) -> PathBuf { - self.base_dir().join("logs") - } - - - // --- FILES --- - - #[must_use] - pub fn db_file(&self) -> PathBuf { - self.base_dir().join("user_data.db") - } - - #[must_use] - pub fn settings_file(&self) -> PathBuf { - self.base_dir().join("settings.json") - } - - // --- GAME DIRECTORIES --- - - /// Get the `config_dir/metadata` folder within the core config directory. - #[inline] - #[must_use] - pub fn metadata_dir(&self) -> PathBuf { - self.base_dir().join("metadata") - } - - /// Get the `config_dir/metadata/libraries` folder for Minecraft libraries. - #[must_use] - pub fn libraries_dir(&self) -> PathBuf { - self.metadata_dir().join("libraries") - } - - /// Get the `config_dir/metadata/natives` folder for Minecraft natives. - #[must_use] - pub fn natives_dir(&self) -> PathBuf { - self.metadata_dir().join("natives") - } - - /// Get the `config_dir/metadata/java` directory. - #[must_use] - pub fn java_dir(&self) -> PathBuf { - self.metadata_dir().join("java") - } - - /// Get the `config_dir/metadata/caches` directory. - #[must_use] - pub fn caches_dir(&self) -> PathBuf { - self.metadata_dir().join("caches") - } -} - -#[derive(Debug, thiserror::Error)] -pub enum DirectoryError { - #[error("Failed to get the base directory for the launcher.")] - BaseDir, -} - diff --git a/packages/core_new/src/store/mod.rs b/packages/core_new/src/store/mod.rs deleted file mode 100644 index 37528f39..00000000 --- a/packages/core_new/src/store/mod.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub(super) mod db; -pub mod ingress; -pub mod proxy; -mod dirs; -mod settings; -mod state; - -pub use dirs::*; -pub use settings::*; -pub use state::*; \ No newline at end of file diff --git a/packages/core_new/src/store/settings.rs b/packages/core_new/src/store/settings.rs deleted file mode 100644 index 8da723a6..00000000 --- a/packages/core_new/src/store/settings.rs +++ /dev/null @@ -1,75 +0,0 @@ -use serde::{Deserialize, Serialize}; -use sqlx::prelude::FromRow; - -use crate::{send_warning, utils::io, LauncherResult}; - -use super::Dirs; - -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Debug, Serialize, Deserialize, Clone)] -#[serde(default)] -pub struct Settings { - pub global_game_settings: SettingsProfile, - pub allow_parallel_running_clusters: bool, - pub enable_gamemode: bool, - pub discord_enabled: bool, - pub settings_version: u32, -} - -impl Default for Settings { - fn default() -> Self { - Self { - global_game_settings: SettingsProfile { - name: "Global".into(), - ..Default::default() - }, - allow_parallel_running_clusters: false, - discord_enabled: false, - enable_gamemode: false, - settings_version: 2, - } - } -} - -impl Settings { - #[tracing::instrument] - pub async fn new() -> Self { - match Self::read().await { - Ok(settings) => settings, - Err(err) => { - send_warning!("Failed to read settings file: {}", err); - Self::default() - }, - } - } - - async fn read() -> LauncherResult { - let path = Dirs::get().await?.settings_file(); - let data = io::read(path).await?; - Ok(serde_json::from_slice(&data)?) - } - - pub async fn save(&self) -> LauncherResult<()> { - let path = Dirs::get().await?.settings_file(); - let data = serde_json::to_string_pretty(self)?; - io::write(path, data).await?; - - Ok(()) - } -} - -#[cfg_attr(feature = "specta", derive(specta::Type))] -#[derive(Default, Debug, Clone, Serialize, Deserialize, FromRow)] -pub struct SettingsProfile { - pub name: String, - pub java_id: Option, - pub res_w: Option, - pub res_h: Option, - pub force_fullscreen: Option, - pub mem_max: Option, - pub launch_args: Option, - pub launch_env: Option, - pub hook_pre: Option, - pub hook_wrapper: Option, - pub hook_post: Option, -} \ No newline at end of file diff --git a/packages/core_new/src/utils/mod.rs b/packages/core_new/src/utils/mod.rs deleted file mode 100644 index 678b90ea..00000000 --- a/packages/core_new/src/utils/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod io; \ No newline at end of file diff --git a/packages/core_new/Cargo.toml b/packages/core_old/Cargo.toml similarity index 67% rename from packages/core_new/Cargo.toml rename to packages/core_old/Cargo.toml index 162c1db2..64bc1edb 100644 --- a/packages/core_new/Cargo.toml +++ b/packages/core_old/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "onelauncher_new" +name = "onelauncher" description = "The core of OneLauncher" version = { workspace = true } license = { workspace = true } @@ -10,75 +10,67 @@ readme = { workspace = true } homepage = { workspace = true } authors = { workspace = true } -[lib] -path = "src/lib.rs" - [features] -default = [ "cli" ] -tauri = [ - "dep:tauri", - "dep:tauri-specta", - "specta", - "gui" -] +default = [] +# feature flag allowing us to interact with tauri (for loading animations, errors showing on gui, etc) +# also allows us to compile onelauncher core without tauri +tauri = [ "dep:tauri", "dep:tauri-specta", "specta" ] specta = [ "dep:specta" ] cli = [ "dep:indicatif" ] -gui = [] [lints] workspace = true [dependencies] +# features[default] +onelauncher_macros = { workspace = true } +onelauncher_utils = { workspace = true } interpulse = { workspace = true } - -# logging tracing = { workspace = true } tracing-subscriber = { workspace = true } tracing-error = { workspace = true } tracing-appender = { workspace = true } - -# serialization +notify = { workspace = true } +notify-debouncer-mini = { workspace = true } +iota_stronghold = { workspace = true } +zeroize = { workspace = true } +tokio = { workspace = true } serde = { workspace = true } serde_json = { workspace = true } serde_ini = { workspace = true } serde_repr = { workspace = true } serde_with = { workspace = true } - -# utils -sqlx = { workspace = true } -tokio = { workspace = true } -tokio-stream = { workspace = true } +paste = { workspace = true } futures = { workspace = true } +zip = { workspace = true } uuid = { workspace = true } thiserror = { workspace = true } anyhow = { workspace = true } chrono = { workspace = true } reqwest = { workspace = true } -regex = { workspace = true } -sysinfo = { workspace = true } -whoami = { workspace = true } -lazy_static = { workspace = true } -rand = { workspace = true } -url = { workspace = true } -async-trait = { workspace = true } - -# integration -discord-rich-presence = { workspace = true } - -# crypto +dirs = { workspace = true } sha1_smol = { workspace = true } sha2 = { workspace = true } murmur2 = { workspace = true } md5 = { workspace = true } - -# io -zip = { workspace = true } async_zip = { workspace = true } -dirs = { workspace = true } +discord-rich-presence = { workspace = true } +regex = { workspace = true } +sysinfo = { workspace = true } +whoami = { workspace = true } +lazy_static = { workspace = true } +async-tungstenite = { workspace = true } +async-recursion = { workspace = true } +tokio-stream = { workspace = true } bytes = { workspace = true } +tempfile = { workspace = true } +rand = { workspace = true } +p256 = { workspace = true } +byteorder = { workspace = true } base64 = { workspace = true } -async-compression = { workspace = true } -dunce = { workspace = true } +flate2 = { workspace = true } +toml = { workspace = true } +url = { workspace = true } # features[tauri] tauri = { workspace = true, optional = true } @@ -90,5 +82,11 @@ specta = { workspace = true, optional = true } # features[cli] indicatif = { workspace = true, optional = true } +[build-dependencies] +dotenvy = { workspace = true } + +[target.'cfg(target_os = "windows")'.dependencies] +winreg = { workspace = true } + [target.'cfg(target_os = "linux")'.dependencies] onelauncher_gamemode = { workspace = true } diff --git a/packages/macros/package.json b/packages/core_old/package.json similarity index 80% rename from packages/macros/package.json rename to packages/core_old/package.json index 3b313f7e..16527a58 100644 --- a/packages/macros/package.json +++ b/packages/core_old/package.json @@ -1,12 +1,12 @@ { - "name": "@onelauncher/macros", + "name": "@onelauncher/core_old", "version": "0.1.0-alpha.2", - "description": "Next-generation open source Minecraft launcher macros", + "description": "Next-generation open source Minecraft launcher core", "license": "GPL-3.0-only", "repository": { "type": "git", "url": "git@github.com:polyfrost/onelauncher", - "directory": "packages/macros" + "directory": "packages/core_old" }, "bugs": "https://github.com/polyfrost/onelauncher/issues", "sideEffects": false, diff --git a/packages/core/src/api/cluster/content/logger.rs b/packages/core_old/src/api/cluster/content/logger.rs similarity index 100% rename from packages/core/src/api/cluster/content/logger.rs rename to packages/core_old/src/api/cluster/content/logger.rs diff --git a/packages/core/src/api/cluster/content/mod.rs b/packages/core_old/src/api/cluster/content/mod.rs similarity index 100% rename from packages/core/src/api/cluster/content/mod.rs rename to packages/core_old/src/api/cluster/content/mod.rs diff --git a/packages/core/src/api/cluster/content/package.rs b/packages/core_old/src/api/cluster/content/package.rs similarity index 100% rename from packages/core/src/api/cluster/content/package.rs rename to packages/core_old/src/api/cluster/content/package.rs diff --git a/packages/core/src/api/cluster/content/screenshots.rs b/packages/core_old/src/api/cluster/content/screenshots.rs similarity index 100% rename from packages/core/src/api/cluster/content/screenshots.rs rename to packages/core_old/src/api/cluster/content/screenshots.rs diff --git a/packages/core/src/api/cluster/content/worlds.rs b/packages/core_old/src/api/cluster/content/worlds.rs similarity index 100% rename from packages/core/src/api/cluster/content/worlds.rs rename to packages/core_old/src/api/cluster/content/worlds.rs diff --git a/packages/core/src/api/cluster/create.rs b/packages/core_old/src/api/cluster/create.rs similarity index 100% rename from packages/core/src/api/cluster/create.rs rename to packages/core_old/src/api/cluster/create.rs diff --git a/packages/core/src/api/cluster/mod.rs b/packages/core_old/src/api/cluster/mod.rs similarity index 100% rename from packages/core/src/api/cluster/mod.rs rename to packages/core_old/src/api/cluster/mod.rs diff --git a/packages/core/src/api/cluster/update.rs b/packages/core_old/src/api/cluster/update.rs similarity index 100% rename from packages/core/src/api/cluster/update.rs rename to packages/core_old/src/api/cluster/update.rs diff --git a/packages/core/src/api/handler.rs b/packages/core_old/src/api/handler.rs similarity index 100% rename from packages/core/src/api/handler.rs rename to packages/core_old/src/api/handler.rs diff --git a/packages/core_old/src/api/ingress.rs b/packages/core_old/src/api/ingress.rs new file mode 100644 index 00000000..8ba5fd71 --- /dev/null +++ b/packages/core_old/src/api/ingress.rs @@ -0,0 +1,5 @@ +use crate::store::{IngressProcessType, IngressProcessor}; + +pub async fn check_ingress_feeds() -> crate::Result { + IngressProcessor::finished(IngressProcessType::IngressFeed).await +} diff --git a/packages/core/src/api/java.rs b/packages/core_old/src/api/java.rs similarity index 100% rename from packages/core/src/api/java.rs rename to packages/core_old/src/api/java.rs diff --git a/packages/core/src/api/metadata.rs b/packages/core_old/src/api/metadata.rs similarity index 100% rename from packages/core/src/api/metadata.rs rename to packages/core_old/src/api/metadata.rs diff --git a/packages/core/src/api/minecraft.rs b/packages/core_old/src/api/minecraft.rs similarity index 100% rename from packages/core/src/api/minecraft.rs rename to packages/core_old/src/api/minecraft.rs diff --git a/packages/core_old/src/api/mod.rs b/packages/core_old/src/api/mod.rs new file mode 100644 index 00000000..b8653854 --- /dev/null +++ b/packages/core_old/src/api/mod.rs @@ -0,0 +1,31 @@ +//! **`OneLauncher` API** +//! +//! API for interacting with our Rust core. + +pub mod cluster; +pub mod handler; +pub mod ingress; +pub mod java; +pub mod metadata; +pub mod minecraft; +pub mod package; +pub mod processor; +pub mod proxy; +pub mod settings; + +pub mod data { + pub use crate::store::{ + ClusterMeta, Credentials, Directories, InitHooks, JavaOptions, Loader, ManagedDependency, + ManagedPackage, ManagedUser, ManagedVersion, Memory, MinecraftCredentials, PackageData, + PackageType, Resolution, Settings, + }; +} + +pub mod prelude { + pub use crate::cluster::{self, create, Cluster}; + pub use crate::data::*; + pub use crate::proxy::InternetPayload; + pub use crate::store::{ClusterPath, JavaVersions, PackageDependency, PackagePath}; + pub use crate::utils::java::JavaVersion; + pub use crate::{java, metadata, minecraft, package, processor, settings, State}; +} diff --git a/packages/core/src/api/package/content/curseforge.rs b/packages/core_old/src/api/package/content/curseforge.rs similarity index 100% rename from packages/core/src/api/package/content/curseforge.rs rename to packages/core_old/src/api/package/content/curseforge.rs diff --git a/packages/core/src/api/package/content/mod.rs b/packages/core_old/src/api/package/content/mod.rs similarity index 100% rename from packages/core/src/api/package/content/mod.rs rename to packages/core_old/src/api/package/content/mod.rs diff --git a/packages/core/src/api/package/content/modrinth.rs b/packages/core_old/src/api/package/content/modrinth.rs similarity index 100% rename from packages/core/src/api/package/content/modrinth.rs rename to packages/core_old/src/api/package/content/modrinth.rs diff --git a/packages/core/src/api/package/content/skyclient.rs b/packages/core_old/src/api/package/content/skyclient.rs similarity index 100% rename from packages/core/src/api/package/content/skyclient.rs rename to packages/core_old/src/api/package/content/skyclient.rs diff --git a/packages/core/src/api/package/from.rs b/packages/core_old/src/api/package/from.rs similarity index 100% rename from packages/core/src/api/package/from.rs rename to packages/core_old/src/api/package/from.rs diff --git a/packages/core/src/api/package/import/atlauncher.rs b/packages/core_old/src/api/package/import/atlauncher.rs similarity index 100% rename from packages/core/src/api/package/import/atlauncher.rs rename to packages/core_old/src/api/package/import/atlauncher.rs diff --git a/packages/core/src/api/package/import/curseforge.rs b/packages/core_old/src/api/package/import/curseforge.rs similarity index 100% rename from packages/core/src/api/package/import/curseforge.rs rename to packages/core_old/src/api/package/import/curseforge.rs diff --git a/packages/core/src/api/package/import/ftb.rs b/packages/core_old/src/api/package/import/ftb.rs similarity index 100% rename from packages/core/src/api/package/import/ftb.rs rename to packages/core_old/src/api/package/import/ftb.rs diff --git a/packages/core/src/api/package/import/gdlauncher.rs b/packages/core_old/src/api/package/import/gdlauncher.rs similarity index 100% rename from packages/core/src/api/package/import/gdlauncher.rs rename to packages/core_old/src/api/package/import/gdlauncher.rs diff --git a/packages/core/src/api/package/import/mod.rs b/packages/core_old/src/api/package/import/mod.rs similarity index 100% rename from packages/core/src/api/package/import/mod.rs rename to packages/core_old/src/api/package/import/mod.rs diff --git a/packages/core/src/api/package/import/modrinth.rs b/packages/core_old/src/api/package/import/modrinth.rs similarity index 100% rename from packages/core/src/api/package/import/modrinth.rs rename to packages/core_old/src/api/package/import/modrinth.rs diff --git a/packages/core/src/api/package/import/multibased.rs b/packages/core_old/src/api/package/import/multibased.rs similarity index 100% rename from packages/core/src/api/package/import/multibased.rs rename to packages/core_old/src/api/package/import/multibased.rs diff --git a/packages/core/src/api/package/import/technic.rs b/packages/core_old/src/api/package/import/technic.rs similarity index 100% rename from packages/core/src/api/package/import/technic.rs rename to packages/core_old/src/api/package/import/technic.rs diff --git a/packages/core/src/api/package/import/tlauncher.rs b/packages/core_old/src/api/package/import/tlauncher.rs similarity index 100% rename from packages/core/src/api/package/import/tlauncher.rs rename to packages/core_old/src/api/package/import/tlauncher.rs diff --git a/packages/core/src/api/package/infer/mod.rs b/packages/core_old/src/api/package/infer/mod.rs similarity index 100% rename from packages/core/src/api/package/infer/mod.rs rename to packages/core_old/src/api/package/infer/mod.rs diff --git a/packages/core/src/api/package/mod.rs b/packages/core_old/src/api/package/mod.rs similarity index 100% rename from packages/core/src/api/package/mod.rs rename to packages/core_old/src/api/package/mod.rs diff --git a/packages/core/src/api/package/mrpack.rs b/packages/core_old/src/api/package/mrpack.rs similarity index 100% rename from packages/core/src/api/package/mrpack.rs rename to packages/core_old/src/api/package/mrpack.rs diff --git a/packages/core/src/api/package/zip.rs b/packages/core_old/src/api/package/zip.rs similarity index 100% rename from packages/core/src/api/package/zip.rs rename to packages/core_old/src/api/package/zip.rs diff --git a/packages/core/src/api/processor.rs b/packages/core_old/src/api/processor.rs similarity index 100% rename from packages/core/src/api/processor.rs rename to packages/core_old/src/api/processor.rs diff --git a/packages/core_old/src/api/proxy/mod.rs b/packages/core_old/src/api/proxy/mod.rs new file mode 100644 index 00000000..d8fb9bb4 --- /dev/null +++ b/packages/core_old/src/api/proxy/mod.rs @@ -0,0 +1,277 @@ +//! Proxy for Tauri/CLI specific features and communication +use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::path::PathBuf; +use std::sync::Arc; +use tokio::sync::{OnceCell, RwLock}; +use uuid::Uuid; + +use crate::store::{ClusterPath, IngressProcessor}; + +pub mod send; +pub mod utils; +pub use utils::*; + +static PROXY_STATE: OnceCell> = OnceCell::const_new(); +pub struct ProxyState { + #[cfg(feature = "tauri")] + pub app: tauri::AppHandle, + pub ingress_feeds: RwLock>, +} + +#[derive(Serialize, Debug, Clone)] +pub struct Ingress { + pub ingress_uuid: Uuid, + pub message: String, + pub ingress_type: IngressType, + pub total: f64, + pub current: f64, + #[serde(skip)] + pub last_sent: f64, + #[cfg(feature = "cli")] + #[serde(skip)] + pub cli: indicatif::ProgressBar, +} + +#[derive(Serialize, Debug, Clone)] +pub struct IngressId(Uuid); + +impl Drop for IngressId { + #[clippy::has_significant_drop] + fn drop(&mut self) { + let ingress_uuid = self.0; + tokio::spawn(async move { + if let Ok(proxy_state) = ProxyState::get().await { + let mut ingress_feeds = proxy_state.ingress_feeds.write().await; + #[cfg(any(feature = "tauri", feature = "cli"))] + if let Some(ingress) = ingress_feeds.remove(&ingress_uuid) { + #[cfg(feature = "cli")] + { + let cli = ingress.cli; + cli.finish(); + } + + #[cfg(feature = "tauri")] + { + use tauri::Emitter; + let event = ingress.ingress_type.clone(); + let fraction = ingress.current / ingress.total; + + let _ = proxy_state.app.emit( + "ingress", + IngressPayload { + fraction: None, + message: "Complete".to_string(), + event, + ingress_uuid, + }, + ); + + tracing::trace!("exited at {fraction} for ingress: {:?}", ingress_uuid); + } + } + + #[cfg(not(any(feature = "tauri", feature = "cli")))] + ingress_feeds.remove(&ingress_uuid); + } + + if crate::State::initalized() { + let _ = IngressProcessor::finish( + crate::store::IngressProcessType::IngressFeed, + ingress_uuid, + ) + .await; + } + }); + } +} + +impl ProxyState { + #[cfg(feature = "tauri")] + pub async fn initialize(handle: &tauri::AppHandle) -> crate::Result> { + PROXY_STATE + .get_or_try_init(|| async { + Ok(Arc::new(Self { + app: handle.clone(), + ingress_feeds: RwLock::new(HashMap::new()), + })) + }) + .await + .cloned() + } + + #[cfg(not(feature = "tauri"))] + pub async fn initialize() -> crate::Result> { + PROXY_STATE + .get_or_try_init(|| async { + Ok(Arc::new(Self { + ingress_feeds: RwLock::new(HashMap::new()), + })) + }) + .await + .cloned() + } + + #[cfg(feature = "tauri")] + pub async fn get_main_window() -> crate::Result { + use tauri::Manager; + let value = Self::get().await?; + Ok(value.app.get_webview_window("main").unwrap()) + } + + #[allow(clippy::unused_async)] + #[cfg(feature = "tauri")] + pub async fn get() -> crate::Result> { + Ok(PROXY_STATE.get().ok_or(ProxyError::NotInitialized)?.clone()) + } + + #[cfg(not(feature = "tauri"))] + pub async fn get() -> crate::Result> { + Self::initialize().await + } + + pub async fn list_ingress_feeds() -> crate::Result> { + let value = Self::get().await?; + let read = value.ingress_feeds.read().await; + + let mut display_list: HashMap = HashMap::new(); + for (uuid, ingress) in read.iter() { + display_list.insert(*uuid, ingress.clone()); + } + + Ok(display_list) + } +} + +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Deserialize, Clone, Debug, Hash, PartialEq, Eq)] +#[serde(tag = "type")] +#[serde(rename_all = "snake_case")] +pub enum IngressType { + Initialize, + DownloadJava { + version: u32, + }, + DownloadLoader { + cluster_path: PathBuf, + cluster_name: String, + }, + SyncCluster { + cluster_path: PathBuf, + cluster_name: String, + }, + InferPackages, + CopyCluster { + import: PathBuf, + cluster_name: String, + }, + SyncConfig { + new_path: PathBuf, + }, + Archival { + cluster_path: PathBuf, + cluster_name: String, + }, + DownloadPackage { + cluster_path: PathBuf, + package_name: String, + icon: Option, + package_id: Option, + package_version: Option, + }, + DownloadPack { + cluster_path: PathBuf, + package_name: String, + icon: Option, + package_version: String, + }, +} + +#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +pub struct IngressPayload { + pub event: IngressType, + pub ingress_uuid: Uuid, + pub fraction: Option, + pub message: String, +} + +#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +pub struct OfflinePayload { + pub offline: bool, +} + +#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +pub struct MessagePayload { + pub message: String, +} + +#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +#[serde(tag = "event")] +pub enum InternetPayload { + InstallPackage { id: String }, + InstallPack { id: String }, + InstallPath { path: PathBuf }, +} + +#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +pub struct ProcessPayload { + pub uuid: Uuid, + pub pid: u32, + pub event: ProcessPayloadType, + pub message: String, +} + +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone, Debug)] +#[serde(rename_all = "snake_case")] +pub enum ProcessPayloadType { + Started, + Modified, + Finished, + Logging, +} + +#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +pub struct ClusterPayload { + pub uuid: Uuid, + pub cluster_path: ClusterPath, + pub path: PathBuf, + pub name: String, + pub event: ClusterPayloadType, +} + +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Serialize, Clone)] +#[serde(rename_all = "snake_case")] +pub enum ClusterPayloadType { + Created, + Inserted, + Synced, + Edited, + Deleted, +} + +#[derive(Debug, thiserror::Error)] +pub enum ProxyError { + #[error("event state was not initialized!")] + NotInitialized, + + #[error("non-existant ingress of key: {0}")] + NoIngressFound(Uuid), + + #[cfg(feature = "tauri")] + #[error("Tauri error: {0}")] + TauriError(#[from] tauri::Error), +} diff --git a/packages/core/src/api/proxy/send.rs b/packages/core_old/src/api/proxy/send.rs similarity index 100% rename from packages/core/src/api/proxy/send.rs rename to packages/core_old/src/api/proxy/send.rs diff --git a/packages/core/src/api/proxy/utils.rs b/packages/core_old/src/api/proxy/utils.rs similarity index 100% rename from packages/core/src/api/proxy/utils.rs rename to packages/core_old/src/api/proxy/utils.rs diff --git a/packages/core/src/api/settings.rs b/packages/core_old/src/api/settings.rs similarity index 100% rename from packages/core/src/api/settings.rs rename to packages/core_old/src/api/settings.rs diff --git a/packages/core_new/src/constants.rs b/packages/core_old/src/constants.rs similarity index 83% rename from packages/core_new/src/constants.rs rename to packages/core_old/src/constants.rs index 20b17852..515cf5f5 100644 --- a/packages/core_new/src/constants.rs +++ b/packages/core_old/src/constants.rs @@ -1,14 +1,11 @@ //! **`OneLauncher` Constants** //! //! Public constant variables and strings that are used throughout the launcher. +//! Can be shared publically, any secrets should be stored in [`crate::store::credentials`]. // =========== Core Metadata =========== /// The name of the launcher. -pub const NAME: &str = match option_env!("LAUNCHER_NAME") { - Some(name) => name, - None => "OneLauncher", -}; - +pub const NAME: &str = "OneLauncher"; /// The version of the launcher (from `../Cargo.toml` env). pub const VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -41,7 +38,7 @@ pub const MODRINTH_API_URL: &str = "https://api.modrinth.com/v2"; pub const MODRINTH_V3_API_URL: &str = "https://api.modrinth.com/v3"; /// The Curseforge API base url. pub const CURSEFORGE_API_URL: &str = "https://api.curseforge.com"; -/// The Curseforge API key. Reserved for use in Polyfrost projects only. Do not use in other projects without permission from the Polyfrost team. +/// The Curseforge API key. Reserved for use in OneLauncher projects only. Do not use in other projects without permission from the OneLauncher team. pub const CURSEFORGE_API_KEY: &str = "$2a$10$6utA1UNSmFPrE/Lh7b7ndeeGmiOkjKNY8kpFB0fsmE/d42ZAfFgCe"; /// The Minecraft game ID on Curseforge. pub const CURSEFORGE_GAME_ID: u32 = 432; @@ -51,7 +48,7 @@ pub const METADATA_API_URL: &str = "https://meta.polyfrost.org"; pub const FEATURED_PACKAGES_URL: &str = "https://polyfrost.org/meta/onelauncher/featured.json"; /// / API base url. pub const MCLOGS_API_URL: &str = "https://api.mclo.gs/1"; -/// metadata base url. +/// https://skyclient.co/ metadata base url. pub const SKYCLIENT_BASE_URL: &str = "https://raw.githubusercontent.com/SkyblockClient/SkyblockClient-REPO/refs/heads/main/v1"; // =========== Paths =========== @@ -59,6 +56,10 @@ pub const SKYCLIENT_BASE_URL: &str = "https://raw.githubusercontent.com/Skyblock /// /// [`Settings`]: crate::store::Settings pub const SETTINGS_FILE: &str = "settings.json"; +/// The public `cluster.json` file used to store the global [`Clusters`] state. +/// +/// [`Clusters`]: crate::store::Clusters +pub const CLUSTER_FILE: &str = "cluster.json"; /// The public `authentication.json` file used to store the global [`MinecraftAuth`] state. /// /// [`MinecraftAuth`]: crate::store::MinecraftAuth @@ -74,6 +75,15 @@ pub const PROCESSOR_FILE: &str = "processor.json"; /// [`Settings`]: crate::store::Settings pub const CURRENT_SETTINGS_FORMAT_VERSION: u32 = 1; +/// The constant core caches folder. +pub const CACHES_FOLDER: &str = "caches"; +/// The constant core crash reports folder. +pub const CRASH_PATH: &str = "crash-reports"; +/// The constant core clusters folder. +pub const CLUSTERS_FOLDER: &str = "clusters"; +/// The constant core metadata folder. +pub const METADATA_FOLDER: &str = "metadata"; + // =========== Hacky Mojang-spec OS constants =========== #[cfg(target_os = "windows")] pub const TARGET_OS: &str = "windows"; diff --git a/packages/core_old/src/error.rs b/packages/core_old/src/error.rs new file mode 100644 index 00000000..b701b997 --- /dev/null +++ b/packages/core_old/src/error.rs @@ -0,0 +1,180 @@ +//! **`OneLauncher` Errors** +//! +//! Public wrappers around common `OneLauncher` errors. + +use tracing_error::InstrumentError; + +/// A standardized [`thiserror::Error`] type that is used across the launcher +#[derive(thiserror::Error, Debug)] +pub enum ErrorKind { + /// Wrapper around [`tokio::sync::AcquireError`] to handle sempahore errors. + #[error("failed to acquire a tokio semaphore: {0}")] + AcquireError(#[from] tokio::sync::AcquireError), + + /// Wrapper around [`tokio::sync::oneshot::error::RecvError`] to handle recieve errors. + #[error("failed to handle async reciever: {0}")] + RecvError(#[from] tokio::sync::oneshot::error::RecvError), + + /// Wrapper around [`tokio::task::JoinError`] to handle tokio join handle errors. + #[error("failed to handle an async task: {0}")] + JoinError(#[from] tokio::task::JoinError), + + /// Wrapper around [`flate2::CompressError`] to handle flate compression errors. + #[error("failed to compress a file with flate: {0}")] + FlateError(#[from] flate2::CompressError), + + /// Wrapper around [`flate2::DecompressError`] to handle flate decompression errors. + #[error("failed to decompress a file with flate: {0}")] + DeflateError(#[from] flate2::DecompressError), + + /// Wrapper around [`uuid::Error`] to handle UUID parsing errors. + #[error("failed to parse and handle uuids: {0}")] + UUIDError(#[from] uuid::Error), + + /// Wrapper around [`interpulse::Error`] to handle interpulse errors. + #[error("failed to parse and handle metadata: {0}")] + MetadataError(#[from] interpulse::Error), + + /// Wrapper around [`serde_json::Error`] to handle Serde JSON parsing errors. + #[error("failed to manage serialization of json: {0}")] + SerdeError(#[from] serde_json::Error), + + /// Wrapper around [`serde_ini::de::Error`] to handle Serde INI parsing errors. + #[error("failed to manage deserialization of ini: {0}")] + INIError(#[from] serde_ini::de::Error), + + /// Wrapper around [`reqwest::Error`] to handle HTTP errors. + #[error("failed to establish an http connection: {0}")] + HTTPError(#[from] reqwest::Error), + + /// Wrapper around [`zip::result::ZipError`] to handle zip errors. + #[error("failed to manage zip files: {0}")] + ZipError(#[from] zip::result::ZipError), + + /// Wrapper around [`async_zip::error::ZipError`] to handle async zip errors. + #[error("failed to manage zip files asynchronously: {0}")] + AsyncZipError(#[from] async_zip::error::ZipError), + + /// Wrapper around [`anyhow::Error`] to handle generic errors. + #[error(transparent)] + AnyhowError(#[from] anyhow::Error), + + /// Wrapper around [`chrono::ParseError`] to handle date parsing errors. + #[error("failed to parse and handle datetime: {0}")] + ChronoError(#[from] chrono::ParseError), + + /// Wrapper around [`crate::state::DirectoryError`] to handle directory errors. + #[error("failed to get directory: {0}")] + DirectoryError(#[from] crate::store::DirectoryError), + + /// Wrapper around [`crate::api::proxy::ProxyError`] to handle ingress errors. + #[error("failed to handle api communication: {0}")] + ProxyError(#[from] crate::api::proxy::ProxyError), + + /// Wrapper around [`crate::store::MinecraftAuthError`] to handle Minecraft auth errors. + #[error("failed to authenticate with microsoft: {0}")] + AuthError(#[from] crate::store::MinecraftAuthError), + + /// Wrapper around [`crate::api::cluster::create::CreateClusterError`] to handle Cluster creation errors. + #[error("failed to create clusters: {0}")] + CreateClusterError(#[from] crate::api::cluster::create::CreateClusterError), + + /// Wrapper around [`notify:Error`] to handle file watching errors. + #[error("failed to watch file {0}")] + NotifyError(#[from] notify::Error), + + /// Wrapper around [`regex::Error`] to handle `RegExp` errors. + #[error("string verification with regex failed: {0}")] + RegexError(#[from] regex::Error), + + /// Wrapper around [`reqwest::header::ToStrError`] to handle header conversion errors. + #[error("failed to convert header to string: {0}")] + HeaderToStrError(#[from] reqwest::header::ToStrError), + + /// Wrapper around [`async_tungstenite::tungstenite::Error`] to handle WebSocket errors. + #[error("failed to handle websocket connection: {0}")] + WebSocketError(#[from] async_tungstenite::tungstenite::Error), + + /// Indicates an error with SHA checksum. + #[error("checksum {0} did not match {1}!")] + HashError(String, String), + + /// Wrapper around [`onelauncher_utils::io::IOError`] to handle wrapped `std::io` errors. + #[error("error handling IO operations: {0}")] + IOError(#[from] onelauncher_utils::io::IOError), + + /// Wrapper around [`std::io::Error`] to handle non-wrapped `std::io` errors. + #[error("error handling standard IO operations: {0}")] + StdIOError(#[from] std::io::Error), + + /// Wrapper around [`crate::utils::java::JavaError`] to handle java errors. + #[error("failed to manage java installations: {0}")] + JavaError(#[from] crate::utils::java::JavaError), + + /// Wrapper around [`crate::store::StrongholdError`] to handle stronghold errors. + #[error("failed to manage credentials with IOTA stronghold: {0}")] + StrongholdError(#[from] crate::store::StrongholdError), + + /// Wrapper around [`url::ParseError`] to handle URL parsing errors + #[error("failed to parse and handle URLs: {0}")] + URLError(#[from] url::ParseError), + + /// Wrapper around [`tauri::Error`] to handle Tauri errors when the feature flag is enabled + #[cfg(feature = "tauri")] + #[error("error handling tauri: {0}")] + TauriError(#[from] tauri::Error), +} + +/// A safe, accessible error structure wrapper around [`ErrorKind`] for use with [`tracing_error`]. +#[derive(Debug)] +pub struct Error { + /// The raw, inner [`ErrorKind`], wrapped in an [`Arc`]. + pub raw: std::sync::Arc, + /// The traced [`ErrorKind`] ([`tracing_error`]) to be parsed and logged. + pub source: tracing_error::TracedError>, +} + +impl From for String { + /// Converts an [`Error`] into a [`String`] value. + fn from(value: Error) -> Self { + value.to_string() + } +} + +impl std::error::Error for Error { + /// Get the source for the inner traced [`Error`]. + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.source.source() + } +} + +impl std::fmt::Display for Error { + /// Format the [`Error`] and output it into the formatter buffer. + fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(fmt, "{}", self.source) + } +} + +impl> From for Error { + /// Converts an [`ErrorKind`] error into a traced [`Error`]. + /// Useful for reducing error mapping and standardizing error types. + fn from(source: E) -> Self { + let error = Into::::into(source); + let boxed_error = std::sync::Arc::new(error); + + Self { + raw: boxed_error.clone(), + source: boxed_error.in_current_span(), + } + } +} + +impl ErrorKind { + /// Converts the current [`ErrorKind`] into a traced [`Error`]. + pub fn as_error(self) -> Error { + self.into() + } +} + +/// Alias for a [`core::result::Result`] with the error type [`Error`]. +pub type Result = anyhow::Result; diff --git a/packages/core/src/game/arguments.rs b/packages/core_old/src/game/arguments.rs similarity index 100% rename from packages/core/src/game/arguments.rs rename to packages/core_old/src/game/arguments.rs diff --git a/packages/core/src/game/metadata.rs b/packages/core_old/src/game/metadata.rs similarity index 100% rename from packages/core/src/game/metadata.rs rename to packages/core_old/src/game/metadata.rs diff --git a/packages/core/src/game/mod.rs b/packages/core_old/src/game/mod.rs similarity index 100% rename from packages/core/src/game/mod.rs rename to packages/core_old/src/game/mod.rs diff --git a/packages/core_old/src/lib.rs b/packages/core_old/src/lib.rs new file mode 100644 index 00000000..485488a9 --- /dev/null +++ b/packages/core_old/src/lib.rs @@ -0,0 +1,20 @@ +#![allow(clippy::all)] +//! # `OneLauncher` +//! +//! A library used as a core for our launcher and Rust APIs. + +#[macro_use] +pub mod utils; + +pub mod api; +pub mod constants; +pub mod error; +pub mod game; +pub mod logger; +pub mod store; + +pub use api::proxy::{Ingress, IngressType, ProxyState}; +pub use api::*; +pub use error::*; +pub use logger::start_logger; +pub use store::{InnerPathLinux, State}; diff --git a/packages/core_old/src/logger.rs b/packages/core_old/src/logger.rs new file mode 100644 index 00000000..742a37ca --- /dev/null +++ b/packages/core_old/src/logger.rs @@ -0,0 +1,74 @@ +//! **`OneLauncher` Logger** +//! +//! Public utilities for [`tracing`] logging in `OneLauncher`. +//! +//! - `RUST_LOG=xxx` is a variable which defines tracing configuration (`ERROR > WARN > INFO > DEBUG > TRACE`) +//! - `RUST_LOG="onelauncher=trace"` will show **all** mesages from `OneLauncher` and not other dependencies. +//! - `RUST_LOG="info"` will show info, warn, and error logs. +//! +//! Errors returned to [`tauri`] are displayed as tracing error logs. +//! These errors also include an attached span trace if the error is from a [`tracing_error`] and the level is info, debug, or trace. +//! Tracing errors also provide Sentry metadata to be handled. +//! To set the environment variable on `unix` you can use the following command: `RUST_LOG="xxx" {your command}` +//! +//! The default `RUST_LOG` is `onelauncher=show`, meaning only logs from `OneLauncher` will be displayed at the info, warn, and error levels. + +use tracing_appender::non_blocking::WorkerGuard; + +// TODO: refactor logging and add more env filters. + +/// Initialize the global [`tracing`] logger in development. +#[cfg(debug_assertions)] +#[must_use] +pub fn start_logger() -> Option { + use tracing_subscriber::prelude::*; + + let filter = tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| { + tracing_subscriber::EnvFilter::new("onelauncher=info,onelauncher_gui=info") + }); + + let subscriber = tracing_subscriber::registry() + .with(tracing_subscriber::fmt::layer()) + .with(filter) + .with(tracing_error::ErrorLayer::default()); + + tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); + + None +} + +/// Initialize the global [`tracing`] logger in production. +#[cfg(not(debug_assertions))] +pub fn start_logger() -> Option { + use crate::store::Directories; + use tracing_appender::rolling::{RollingFileAppender, Rotation}; + use tracing_subscriber::fmt::time::ChronoLocal; + use tracing_subscriber::prelude::*; + + let logs_dir = if let Some(directory) = Directories::logs_dir() { + directory + } else { + eprintln!("failed to start logger"); + return None; + }; + + let filter = tracing_subscriber::EnvFilter::try_from_default_env() + .unwrap_or_else(|_| tracing_subscriber::EnvFilter::new("onelauncher=info")); + + let file_appender = RollingFileAppender::new(Rotation::DAILY, logs_dir, "onelauncher.log"); + let (non_blocking, guard) = tracing_appender::non_blocking(file_appender); + + let subscriber = tracing_subscriber::registry() + .with( + tracing_subscriber::fmt::layer() + .with_writer(non_blocking) + .with_ansi(false) + .with_timer(ChronoLocal::rfc_3339()), + ) + .with(filter) + .with(tracing_error::ErrorLayer::default()); + + tracing::subscriber::set_global_default(subscriber).expect("setting default subscriber failed"); + + Some(guard) +} diff --git a/packages/core/src/store/clusters.rs b/packages/core_old/src/store/clusters.rs similarity index 100% rename from packages/core/src/store/clusters.rs rename to packages/core_old/src/store/clusters.rs diff --git a/packages/core/src/store/credentials.rs b/packages/core_old/src/store/credentials.rs similarity index 100% rename from packages/core/src/store/credentials.rs rename to packages/core_old/src/store/credentials.rs diff --git a/packages/core_old/src/store/dirs.rs b/packages/core_old/src/store/dirs.rs new file mode 100644 index 00000000..8eab75de --- /dev/null +++ b/packages/core_old/src/store/dirs.rs @@ -0,0 +1,191 @@ +//! Handles core directory management +use std::path::PathBuf; +use tokio::sync::RwLock; + +use super::Settings; +use crate::constants; + +/// Directory management and utilities. +#[derive(Debug)] +pub struct Directories { + /// Settings: All small caches and the core settings.json + pub settings_dir: PathBuf, + /// Base Configuration: Clusters and all Assets (should be changable as a setting that can go across file systems) + /// By default this should be the same as the `settings_dir` + pub config_dir: RwLock, + /// The current working directory of the directory manager. + pub cwd: PathBuf, +} + +impl Directories { + /// Bootstrap the initial settings directory on first startup. + #[must_use] + pub fn init_settings_dir() -> Option { + Self::env_path("ONELAUNCHER_CONFIG") + .or_else(|| Some(dirs::data_dir()?.join(constants::NAME))) + } + + /// Bootstrap the initial settings directory on first startup. + #[inline] + pub fn init_settings_file() -> crate::Result { + let settings_dir = Self::init_settings_dir().ok_or(DirectoryError::ConfigDir)?; + Ok(settings_dir.join("settings.json")) + } + + /// Initialize the core directory manager + #[tracing::instrument] + pub fn initalize(settings: &Settings) -> crate::Result { + let cwd = std::env::current_dir().map_err(DirectoryError::WorkingDir)?; + let settings_dir = Self::init_settings_dir().ok_or(DirectoryError::ConfigDir)?; + let config_dir = settings + .config_dir + .clone() + .ok_or(DirectoryError::ConfigDir)?; + Ok(Self { + settings_dir, + config_dir: RwLock::new(config_dir), + cwd, + }) + } + + /// Get the `config_dir/metadata` folder within the core config directory. + #[inline] + pub async fn metadata_dir(&self) -> PathBuf { + self.config_dir + .read() + .await + .join(constants::METADATA_FOLDER) + } + + /// Get the `config_dir/metadata/libraries` folder for Minecraft libraries. + #[inline] + pub async fn libraries_dir(&self) -> PathBuf { + self.metadata_dir().await.join("libraries") + } + + /// Get the `config_dir/metadata/java` directory. + #[inline] + pub async fn java_dir(&self) -> PathBuf { + self.metadata_dir().await.join("java_versions") + } + + /// Get the `config_dir/metadata/caches` directory. + #[inline] + pub async fn caches_dir(&self) -> PathBuf { + self.metadata_dir().await.join("caches") + } + + /// Bootstrap the core logs directory and get it as a [`PathBuf`]. + #[inline] + #[must_use] + pub fn logs_dir() -> Option { + Self::init_settings_dir().map(|d| d.join("logs")) + } + + /// Get the `settings_dir/settings.json` file as a [`PathBuf`]. + #[inline] + pub fn settings_file(&self) -> PathBuf { + self.settings_dir.join(constants::SETTINGS_FILE) + } + + /// Get a [`PathBuf`] from a provided environment variable. + #[inline] + fn env_path(name: &str) -> Option { + std::env::var_os(name).map(PathBuf::from) + } + + /// Get the `config_dir/metadata/assets` directory. + #[inline] + pub async fn assets_dir(&self) -> PathBuf { + self.metadata_dir().await.join("assets") + } + + /// Get the `config_dir/metadata/assets/indexes` directory. + #[inline] + pub async fn index_dir(&self) -> PathBuf { + self.assets_dir().await.join("indexes") + } + + /// Get the `config_dir/metadata/assets/objects` directory. + #[inline] + pub async fn objects_dir(&self) -> PathBuf { + self.assets_dir().await.join("objects") + } + + /// Get the `config_dir/metadata/assets/objects/{hash}` directory. + #[inline] + pub async fn object_dir(&self, hash: &str) -> PathBuf { + self.objects_dir().await.join(&hash[..2]).join(hash) + } + + /// Get the `config_dir/clusters` directory. + #[inline] + pub async fn clusters_dir(&self) -> PathBuf { + self.config_dir.read().await.join("clusters") + } + + /// Get the `config_dir/clusters/{uuid}` directory. + #[inline] + pub async fn cluster_dir(&self, uuid: uuid::Uuid) -> PathBuf { + self.clusters_dir().await.join(uuid.to_string()) + } + + /// Get the `{cluster_path}/logs` directory. + #[inline] + pub async fn cluster_logs_dir(cluster_path: &super::ClusterPath) -> crate::Result { + Ok(cluster_path.full_path().await?.join("logs")) + } + + /// Get the `{cluster_path}/crash_reports` directory. + #[inline] + pub async fn crash_reports_dir(cluster_path: &super::ClusterPath) -> crate::Result { + Ok(cluster_path.full_path().await?.join("crash-reports")) + } + + /// Get the `config_dir/metadata/resources` directory. + #[inline] + pub async fn legacy_assets_dir(&self) -> PathBuf { + self.metadata_dir().await.join("resources") + } + + /// Get the `config_dir/metadata/natives` directory. + #[inline] + pub async fn natives_dir(&self) -> PathBuf { + self.metadata_dir().await.join("natives") + } + + /// Get the `config_dir/metadata/natives/{version}` directory. + #[inline] + pub async fn version_natives_dir(&self, version: &str) -> PathBuf { + self.natives_dir().await.join(version) + } + + /// Get the Minecraft `config_dir/metadata/versions` directory. + #[inline] + pub async fn versions_dir(&self) -> PathBuf { + self.metadata_dir().await.join("versions") + } + + /// Get the Minecraft `config_dir/metadata/versions/{version}` directory. + #[inline] + pub async fn version_dir(&self, version: &str) -> PathBuf { + self.versions_dir().await.join(version) + } + + /// Get the `config_dir/icons` directory. + #[inline] + pub async fn icons_dir(&self) -> PathBuf { + self.config_dir.read().await.join("icons") + } +} + +/// Represents a core directory management error. +#[derive(Debug, thiserror::Error)] +pub enum DirectoryError { + /// An error for when a config directory cannot be initialized. + #[error("failed to get the user's config directory")] + ConfigDir, + /// A wrapper over [`std::io::Error`] for cwd fetching errors. + #[error("could not open working directory {0}")] + WorkingDir(std::io::Error), +} diff --git a/packages/core/src/store/discord.rs b/packages/core_old/src/store/discord.rs similarity index 100% rename from packages/core/src/store/discord.rs rename to packages/core_old/src/store/discord.rs diff --git a/packages/core/src/store/java_versions.rs b/packages/core_old/src/store/java_versions.rs similarity index 100% rename from packages/core/src/store/java_versions.rs rename to packages/core_old/src/store/java_versions.rs diff --git a/packages/core/src/store/metadata.rs b/packages/core_old/src/store/metadata.rs similarity index 100% rename from packages/core/src/store/metadata.rs rename to packages/core_old/src/store/metadata.rs diff --git a/packages/core/src/store/minecraft.rs b/packages/core_old/src/store/minecraft.rs similarity index 100% rename from packages/core/src/store/minecraft.rs rename to packages/core_old/src/store/minecraft.rs diff --git a/packages/core_old/src/store/mod.rs b/packages/core_old/src/store/mod.rs new file mode 100644 index 00000000..83e0772a --- /dev/null +++ b/packages/core_old/src/store/mod.rs @@ -0,0 +1,289 @@ +//! **`OneLauncher` Store** +//! +//! Core state and storage management for the launcher, managing all states. + +use std::sync::Arc; +use std::time::Duration; + +use notify::RecommendedWatcher; +use notify_debouncer_mini::Debouncer; +use tokio::sync::{OnceCell, RwLock, Semaphore}; + +use crate::proxy::send::{init_ingress_internal, send_ingress, send_offline}; +use crate::utils::http; +use crate::utils::http::{FetchSemaphore, IoSemaphore}; + +mod dirs; +pub use self::dirs::*; + +mod minecraft; +pub use self::minecraft::*; + +mod credentials; +pub use self::credentials::*; + +mod discord; +pub use self::discord::*; + +mod metadata; +pub use self::metadata::*; + +mod settings; +pub use self::settings::*; + +mod java_versions; +pub use self::java_versions::*; + +mod processor; +pub use self::processor::*; + +mod clusters; +pub use self::clusters::*; + +mod package; +pub use self::package::*; + +mod oneconfig; +pub use self::oneconfig::*; + +/// The static [`OnceCell>`] for storing the global runtime launcher state. +static LAUNCHER_STATE: OnceCell> = OnceCell::const_new(); + +/// The public `OneLauncher` state structure. +pub struct State { + /// Handles a boolean to check if the launcher is connected to the internet + pub offline: RwLock, + /// Handles core launcher directory and files + pub directories: Directories, + + /// Semaphore used to handle concurrent network requests + pub fetch_semaphore: FetchSemaphore, + /// Maximum number of semaphore permits to limit the amount of network requests at one time + pub fetch_semaphore_max: RwLock, + /// Semaphore used to handle concurrent IO requests + pub io_semaphore: IoSemaphore, + /// Maximum number of semaphore permits to limit the amount of IO requests at one time + pub io_semaphore_max: RwLock, + + /// Handles launcher metadata via [`interpulse`] + pub metadata: RwLock, + /// Handles launcher configuration and settings + pub settings: RwLock, + /// Handles minecraft auth flows and users + pub users: RwLock, + /// Handles processes + pub processor: RwLock, + /// Handles `OneConfig` integration with [`async-tungstenite`] + pub oneconfig: RwLock>, + /// Handles secure credential management with [`iota_stronghold`]. + pub credentials: RwLock>, + /// Handles clusters + pub(crate) clusters: RwLock, + /// Handles packages + pub(crate) packages: RwLock, + /// Handles internal ingress processes + pub(crate) ingress_processor: RwLock, + /// Handles file system watching for cluster manager + pub(crate) watcher: RwLock>, + /// Handles Discord rich prescence + pub discord_rpc: DiscordRPC, +} + +impl State { + /// Get the current global launcher state (or initialize it) + pub async fn get() -> crate::Result>> { + Ok(Arc::new( + LAUNCHER_STATE + .get_or_try_init(Self::initialize) + .await? + .read() + .await, + )) + } + + /// Get and lock writing to the current global launcher state (or initalize it) + pub async fn get_and_write() -> crate::Result> { + Ok(LAUNCHER_STATE + .get_or_try_init(Self::initialize) + .await? + .write() + .await) + } + + /// Initializes the core OneLauncher state fully. + #[tracing::instrument] + #[onelauncher_macros::memory] + async fn initialize() -> crate::Result> { + let ingress = + init_ingress_internal(crate::IngressType::Initialize, 100.0, "initializing state") + .await?; + + let settings = Settings::initialize(&Directories::init_settings_file()?).await?; + let directories = Directories::initalize(&settings)?; + send_ingress(&ingress, 10.0, None).await?; + let mut watcher = crate::utils::watcher::initialize_watcher()?; + let fetch_semaphore = + FetchSemaphore(RwLock::new(Semaphore::new(settings.max_async_fetches))); + let io_semaphore = IoSemaphore(RwLock::new(Semaphore::new( + settings.max_async_io_operations, + ))); + send_ingress(&ingress, 10.0, None).await?; + + let is_offline = !http::check_internet_connection(3).await; + + // TODO: Make this run in the background, this delays launcher startup by a couple seconds + let metadata_in = + Metadata::initialize(&directories, !is_offline, &io_semaphore, &fetch_semaphore); + let clusters_in = Clusters::initialize(&directories, &mut watcher); + let users_in = MinecraftState::initialize(&directories, &io_semaphore); + let (metadata, clusters, users) = crate::ingress_join! { + Some(&ingress), 70.0, Some("loading core"); + metadata_in, + clusters_in, + users_in, + }?; + + send_ingress(&ingress, 5.0, Some("loading packages")).await?; + let packages = Packages::initialize(&clusters); + + let ingress_processor = IngressProcessor::new(); + let discord_rpc = DiscordRPC::initialize(is_offline || settings.disable_discord)?; + if !settings.disable_discord && !is_offline { + let _ = discord_rpc.apply_activity("Idling...", true).await; + } + + let processor = Processor::new(); + + Self::status_loop(); + send_ingress(&ingress, 10.0, None).await?; + + Ok::, crate::Error>(RwLock::new(Self { + offline: RwLock::new(is_offline), + directories, + fetch_semaphore, + fetch_semaphore_max: RwLock::new(settings.max_async_fetches as u32), + io_semaphore, + io_semaphore_max: RwLock::new(settings.max_async_io_operations as u32), + metadata: RwLock::new(metadata), + settings: RwLock::new(settings), + users: RwLock::new(users), + processor: RwLock::new(processor), + oneconfig: RwLock::new(None), + credentials: RwLock::new(None), + clusters: RwLock::new(clusters), + packages: RwLock::new(packages), + ingress_processor: RwLock::new(ingress_processor), + watcher: RwLock::new(watcher), + discord_rpc, + })) + } + + /// Initalizes a "game loop" which checks for updates and if we are online. + pub fn status_loop() { + tokio::task::spawn(async { + loop { + let state = Self::get().await; + if let Ok(state) = state { + let _ = state.check_status().await; + } + + tokio::time::sleep(Duration::from_secs(10)).await; + } + }); + } + + /// Updates all data if we are connected to the internet. + pub fn update() { + tokio::task::spawn(async { + let state = Self::get(); + if let Ok(state) = state.await { + if !*state.offline.read().await { + let version_up = Clusters::update_versions(); + let meta_up = Metadata::update(); + let package_up = Clusters::update_packages(); + + let _ = tokio::join!(version_up, meta_up, package_up); + } + } + }); + } + + /// Synchronizes data that can change outside of our control. + #[tracing::instrument] + #[onelauncher_macros::memory] + pub async fn sync() -> crate::Result<()> { + let state = Self::get().await?; + let sync_settings = async { + let state = Arc::clone(&state); + tokio::spawn(async move { + let reader = state.settings.read().await; + reader.sync(&state.directories.settings_file()).await?; + Ok::<_, crate::Error>(()) + }) + .await? + }; + + let sync_clusters = async { + let state = Arc::clone(&state); + + tokio::spawn(async move { + let clusters = state.clusters.read().await; + + clusters.sync().await?; + Ok::<_, crate::Error>(()) + }) + .await? + }; + + tokio::try_join!(sync_settings, sync_clusters)?; + Ok(()) + } + + /// Resets the IO [`Semaphore`] to clear all tasks. + /// # This should ONLY be called when we can ensure + /// # that there are no current tasks running!! + pub async fn reset_io_semaphore(&self) { + let settings = self.settings.read().await; + let mut io_semaphore = self.io_semaphore.0.write().await; + let mut total_permits = self.io_semaphore_max.write().await; + // block ALL semaphore permits - this can be destructive + let _ = io_semaphore.acquire_many(*total_permits).await; + + io_semaphore.close(); + *total_permits = settings.max_async_io_operations as u32; + *io_semaphore = Semaphore::new(settings.max_async_io_operations); + } + + /// Resets the Fetch [`Semaphore`] to clear all tasks. + /// # This should ONLY be called when we can ensure + /// # that there are no current tasks running!! + pub async fn reset_fetch_semaphore(&self) { + let settings = self.settings.read().await; + let mut fetch_semaphore = self.fetch_semaphore.0.write().await; + let mut total_permits = self.fetch_semaphore_max.write().await; + // block ALL semaphore permits - this can be destructive + let _ = fetch_semaphore.acquire_many(*total_permits).await; + + fetch_semaphore.close(); + *total_permits = settings.max_async_io_operations as u32; + *fetch_semaphore = Semaphore::new(settings.max_async_fetches); + } + + /// Checks if we are online used in a loop. + pub async fn check_status(&self) -> crate::Result<()> { + let is_online = http::check_internet_connection(3).await; + let mut offline = self.offline.write().await; + if *offline != is_online { + return Ok(()); + } + + send_offline(!is_online).await?; + *offline = !is_online; + Ok(()) + } + + /// Determine if the global state is initalized or not (wrapper) + pub fn initalized() -> bool { + LAUNCHER_STATE.initialized() + } +} diff --git a/packages/core/src/store/oneconfig.rs b/packages/core_old/src/store/oneconfig.rs similarity index 100% rename from packages/core/src/store/oneconfig.rs rename to packages/core_old/src/store/oneconfig.rs diff --git a/packages/core/src/store/package.rs b/packages/core_old/src/store/package.rs similarity index 100% rename from packages/core/src/store/package.rs rename to packages/core_old/src/store/package.rs diff --git a/packages/core/src/store/processor.rs b/packages/core_old/src/store/processor.rs similarity index 100% rename from packages/core/src/store/processor.rs rename to packages/core_old/src/store/processor.rs diff --git a/packages/core_old/src/store/settings.rs b/packages/core_old/src/store/settings.rs new file mode 100644 index 00000000..c51d0a65 --- /dev/null +++ b/packages/core_old/src/store/settings.rs @@ -0,0 +1,209 @@ +//! Handles user-inputted settings and global values + +use super::{Directories, JavaVersions}; +use crate::constants::CURRENT_SETTINGS_FORMAT_VERSION; +use onelauncher_utils::io; +use serde::{Deserialize, Serialize}; +use std::path::{Path, PathBuf}; + +/// A global settings state for the launcher. +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct Settings { + /// A `OneLauncher` theme managed by the `OneLauncher` GUI. + #[serde(default = "theme_default")] + pub theme: String, + /// A global browser list view for the `OneLauncher` GUI. + #[serde(default)] + pub browser_list_view: BrowserListView, + /// Does not ask for confirmation when closing the `OneLauncher` GUI + #[serde(default)] + pub hide_close_prompt: bool, + /// Disables animations in the `OneLauncher` GUI + #[serde(default)] + pub disable_animations: bool, + /// A global fullscreen Minecraft state. + #[serde(default)] + pub force_fullscreen: bool, + /// Whether to allow launching the same cluster under the same account. + #[serde(default)] + pub allow_parallel_running_clusters: bool, + /// Whether to launch Feral Gamemode on Linux systems. + #[serde(default)] + pub enable_gamemode: bool, + /// A global default [`Resolution`] for Minecraft. + pub resolution: Resolution, + /// A global [`JavaVersions`] list and default version. + pub java_versions: JavaVersions, + /// A global [`Memory`] settings store for Java memory settings. + pub memory: Memory, + /// Global and default initialization hooks . + pub init_hooks: InitHooks, + /// Global and default custom Java arguments. + pub custom_java_args: Vec, + /// Global and default custom environment variables. + pub custom_env_args: Vec<(String, String)>, + /// Global and default maximum [`Semaphore`] I/O operations. + pub max_async_io_operations: usize, + /// Global and default maximum [`Semaphore`] HTTP operations. + pub max_async_fetches: usize, + /// The [`CURRENT_FORMAT_VERSION`] of this settings file. + pub version: u32, + /// Whether or not to disable Discord IPC. + #[serde(default)] + pub disable_discord: bool, + /// Whether or not to enable a debug mode in the launcher. + #[serde(default)] + pub debug_mode: bool, + /// Whether or not to disable Plausible and Sentry analytics. + #[serde(default)] + pub disable_analytics: bool, + /// The core global config directory stored as a [`PathBuf`]. + #[serde(default = "Directories::init_settings_dir")] + pub config_dir: Option, + /// Whether or not to minimize the launcher upon a game launch. + #[serde(default)] + pub hide_on_launch: bool, + /// Enable/disable custom window decorations. + #[serde(default)] + pub custom_frame: bool, + /// Completed onboarding. + #[serde(default)] + pub onboarding_completed: bool, +} + +fn theme_default() -> String { + "dark".to_string() +} + +impl Settings { + /// Initializes the global settings state. + #[tracing::instrument] + pub async fn initialize(file: &Path) -> crate::Result { + let mut recovered_corruption = false; + + let settings = if file.exists() { + let read_settings = io::read(&file) + .await + .map_err(|err| anyhow::anyhow!("error reading settings file: {0}", err).into()) + .and_then(|it| serde_json::from_slice::(&it).map_err(crate::Error::from)); + + if let Err(ref err) = read_settings { + tracing::error!("failed to load settings file: {err}."); + let backup = file.with_extension("json.bak"); + tracing::error!( + "corrupted settings will be backed up as {}, and a new one will be created", + backup.display() + ); + let _ = io::rename(file, backup).await; + recovered_corruption = true; + } + + read_settings.ok() + } else { + None + }; + + if let Some(settings) = settings { + Ok(settings) + } else { + let settings = Self { + theme: "dark".to_string(), + browser_list_view: BrowserListView::Grid, + hide_close_prompt: true, + disable_animations: false, + force_fullscreen: false, + allow_parallel_running_clusters: false, + #[cfg(target_os = "linux")] + enable_gamemode: true, + #[cfg(not(target_os = "linux"))] + enable_gamemode: false, + resolution: Resolution::default(), + java_versions: JavaVersions::new(), + memory: Memory::default(), + init_hooks: InitHooks::default(), + custom_env_args: Vec::new(), + custom_java_args: Vec::new(), + max_async_fetches: 10, + max_async_io_operations: 10, + version: CURRENT_SETTINGS_FORMAT_VERSION, + disable_analytics: false, + disable_discord: false, + debug_mode: false, + config_dir: Directories::init_settings_dir(), + hide_on_launch: false, + custom_frame: true, + onboarding_completed: false, + }; + + if recovered_corruption { + settings.sync(file).await?; + } + + Ok(settings) + } + } + + /// Synchronizes the current settings from a file. + #[tracing::instrument(skip(self))] + pub async fn sync(&self, to: &Path) -> crate::Result<()> { + io::write(to, serde_json::to_vec(self)?).await?; + Ok(()) + } +} + +/// `OneLauncher` browser list type. +#[cfg_attr(feature = "specta", derive(specta::Type))] +#[derive(Default, Debug, Clone, Copy, Serialize, Deserialize)] +#[serde(rename_all = "snake_case")] +pub enum BrowserListView { + #[default] + Grid, + List, +} + +/// Global memory settings across all clusters. +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +#[cfg_attr(feature = "specta", derive(specta::Type))] +pub struct Memory { + /// Maximum amount of Java memory available globally. + pub maximum: u32, + /// Minimum amount of Java memory available globally. + pub minimum: u32, +} + +impl Default for Memory { + fn default() -> Self { + Self { + maximum: 2048, + minimum: 256, + } + } +} + +/// Global Minecraft resolution. +#[derive(Serialize, Deserialize, Debug, Clone, Copy)] +#[cfg_attr(feature = "specta", derive(specta::Type))] +pub struct Resolution(pub u16, pub u16); + +impl Default for Resolution { + fn default() -> Self { + Self(854, 480) + } +} + +/// Global initialization hooks for all Minecraft clusters. +#[derive(Serialize, Deserialize, Debug, Clone, Default)] +#[serde(default)] +#[cfg_attr(feature = "specta", derive(specta::Type))] +pub struct InitHooks { + /// Pre-launch hook. + #[serde(skip_serializing_if = "Option::is_none")] + pub pre: Option, + /// Wrapper hook for the runtime of the game instance. + #[serde(skip_serializing_if = "Option::is_none")] + pub wrapper: Option, + /// Post-launch hook. + #[serde(skip_serializing_if = "Option::is_none")] + pub post: Option, +} diff --git a/packages/core/src/utils/crypto.rs b/packages/core_old/src/utils/crypto.rs similarity index 100% rename from packages/core/src/utils/crypto.rs rename to packages/core_old/src/utils/crypto.rs diff --git a/packages/core/src/utils/http.rs b/packages/core_old/src/utils/http.rs similarity index 100% rename from packages/core/src/utils/http.rs rename to packages/core_old/src/utils/http.rs diff --git a/packages/core/src/utils/java.rs b/packages/core_old/src/utils/java.rs similarity index 100% rename from packages/core/src/utils/java.rs rename to packages/core_old/src/utils/java.rs diff --git a/packages/core_old/src/utils/mod.rs b/packages/core_old/src/utils/mod.rs new file mode 100644 index 00000000..85093225 --- /dev/null +++ b/packages/core_old/src/utils/mod.rs @@ -0,0 +1,15 @@ +//! **`OneLauncher` Core Utilities** +//! Standard asynchronous utilities and wrappers for use within the launcher core. +//! +//! - [`http`]: Async extensions and wrappers around [`reqwest`] functions. +//! - [`java`]: Async utilities for managing and downloading Java versions. +//! - [`watcher`]: Async utilities for watching files with [`notify`]. + +pub mod http; +pub mod java; +pub mod pagination; +pub mod watcher; +pub mod crypto; + +#[cfg(feature = "tauri")] +pub mod window; diff --git a/packages/core/src/utils/pagination.rs b/packages/core_old/src/utils/pagination.rs similarity index 100% rename from packages/core/src/utils/pagination.rs rename to packages/core_old/src/utils/pagination.rs diff --git a/packages/core/src/utils/watcher.rs b/packages/core_old/src/utils/watcher.rs similarity index 100% rename from packages/core/src/utils/watcher.rs rename to packages/core_old/src/utils/watcher.rs diff --git a/packages/core/src/utils/window.rs b/packages/core_old/src/utils/window.rs similarity index 100% rename from packages/core/src/utils/window.rs rename to packages/core_old/src/utils/window.rs diff --git a/packages/core/wrapper/README.md b/packages/core_old/wrapper/README.md similarity index 100% rename from packages/core/wrapper/README.md rename to packages/core_old/wrapper/README.md diff --git a/packages/core/wrapper/forge/.gitkeep b/packages/core_old/wrapper/forge/.gitkeep similarity index 100% rename from packages/core/wrapper/forge/.gitkeep rename to packages/core_old/wrapper/forge/.gitkeep diff --git a/packages/core/wrapper/java/JavaInfo.class b/packages/core_old/wrapper/java/JavaInfo.class similarity index 100% rename from packages/core/wrapper/java/JavaInfo.class rename to packages/core_old/wrapper/java/JavaInfo.class diff --git a/packages/core/wrapper/java/JavaInfo.java b/packages/core_old/wrapper/java/JavaInfo.java similarity index 100% rename from packages/core/wrapper/java/JavaInfo.java rename to packages/core_old/wrapper/java/JavaInfo.java diff --git a/packages/core/wrapper/java/LICENSE b/packages/core_old/wrapper/java/LICENSE similarity index 100% rename from packages/core/wrapper/java/LICENSE rename to packages/core_old/wrapper/java/LICENSE diff --git a/packages/entity/Cargo.toml b/packages/entity/Cargo.toml new file mode 100644 index 00000000..b00817ee --- /dev/null +++ b/packages/entity/Cargo.toml @@ -0,0 +1,28 @@ +[package] +name = "onelauncher_entity" +description = "Database entities for OneLauncher" +version = { workspace = true } +license = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +documentation = { workspace = true } +readme = { workspace = true } +homepage = { workspace = true } +authors = { workspace = true } + +[lib] +name = "onelauncher_entity" +path = "src/lib.rs" + +[features] +default = [] +specta = [ "dep:specta" ] + +[dependencies] +onelauncher_macro = { workspace = true } +sea-orm = { workspace = true } +serde = { workspace = true } +serde_json = { workspace = true } +chrono = { workspace = true } +uuid = { workspace = true } +specta = { workspace = true, optional = true } diff --git a/packages/entity/src/entities/cluster_groups.rs b/packages/entity/src/entities/cluster_groups.rs new file mode 100644 index 00000000..88fdc8fe --- /dev/null +++ b/packages/entity/src/entities/cluster_groups.rs @@ -0,0 +1,28 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "cluster_groups")] +#[onelauncher_macro::specta] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + #[sea_orm(column_type = "Text")] + pub name: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::clusters::Entity")] + Clusters, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Clusters.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/entity/src/entities/clusters.rs b/packages/entity/src/entities/clusters.rs new file mode 100644 index 00000000..163e5025 --- /dev/null +++ b/packages/entity/src/entities/clusters.rs @@ -0,0 +1,66 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "clusters")] +#[onelauncher_macro::specta] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false, column_type = "Text")] + pub path: String, + pub created_at: i32, + pub updated_at: i32, + pub group_id: Option, + #[sea_orm(column_type = "Text")] + pub name: String, + #[sea_orm(column_type = "Text")] + pub mc_version: String, + #[sea_orm(column_type = "Text")] + pub mc_loader: String, + #[sea_orm(column_type = "Text", nullable)] + pub mc_loader_version: Option, + pub last_played: Option, + pub overall_played: Option, + #[sea_orm(column_type = "Text", nullable)] + pub icon_url: Option, + #[sea_orm(column_type = "Text", nullable)] + pub setting_profile_name: Option, + #[sea_orm(column_type = "Text", nullable)] + pub linked_pack_id: Option, + pub linked_pack_version: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm( + belongs_to = "super::cluster_groups::Entity", + from = "Column::GroupId", + to = "super::cluster_groups::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + ClusterGroups, + #[sea_orm( + belongs_to = "super::setting_profiles::Entity", + from = "Column::SettingProfileName", + to = "super::setting_profiles::Column::Name", + on_update = "NoAction", + on_delete = "NoAction" + )] + SettingProfiles, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::ClusterGroups.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::SettingProfiles.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/entity/src/entities/java_versions.rs b/packages/entity/src/entities/java_versions.rs new file mode 100644 index 00000000..aa793ca5 --- /dev/null +++ b/packages/entity/src/entities/java_versions.rs @@ -0,0 +1,33 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "java_versions")] +#[onelauncher_macro::specta] +pub struct Model { + #[sea_orm(primary_key)] + pub id: i32, + pub major_version: i32, + #[sea_orm(column_type = "Text")] + pub display_name: String, + #[sea_orm(column_type = "Text")] + pub absolute_path: String, + #[sea_orm(column_type = "Text")] + pub full_version: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::setting_profiles::Entity")] + SettingProfiles, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::SettingProfiles.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/entity/src/entities/mod.rs b/packages/entity/src/entities/mod.rs new file mode 100644 index 00000000..2f91840a --- /dev/null +++ b/packages/entity/src/entities/mod.rs @@ -0,0 +1,9 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +pub mod prelude; + +pub mod cluster_groups; +pub mod clusters; +pub mod java_versions; +pub mod packages; +pub mod setting_profiles; diff --git a/packages/entity/src/entities/packages.rs b/packages/entity/src/entities/packages.rs new file mode 100644 index 00000000..4bcea7a3 --- /dev/null +++ b/packages/entity/src/entities/packages.rs @@ -0,0 +1,34 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "packages")] +#[onelauncher_macro::specta] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false, column_type = "Text")] + pub file_name: String, + #[sea_orm(column_type = "Text")] + pub display_name: String, + #[sea_orm(column_type = "Text")] + pub display_version: String, + #[sea_orm(primary_key, auto_increment = false)] + pub type_id: i32, + pub provider_id: i32, + #[sea_orm(column_type = "Text")] + pub provider_version: String, + #[sea_orm(column_type = "Text")] + pub mc_versions: String, + #[sea_orm(column_type = "Text")] + pub mc_loader: String, + #[sea_orm(column_type = "Text")] + pub hash: String, + #[sea_orm(column_type = "Text", nullable)] + pub icon_url: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation {} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/entity/src/entities/prelude.rs b/packages/entity/src/entities/prelude.rs new file mode 100644 index 00000000..d7c9cef1 --- /dev/null +++ b/packages/entity/src/entities/prelude.rs @@ -0,0 +1,7 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +pub use super::cluster_groups::Entity as ClusterGroups; +pub use super::clusters::Entity as Clusters; +pub use super::java_versions::Entity as JavaVersions; +pub use super::packages::Entity as Packages; +pub use super::setting_profiles::Entity as SettingProfiles; diff --git a/packages/entity/src/entities/setting_profiles.rs b/packages/entity/src/entities/setting_profiles.rs new file mode 100644 index 00000000..6479b1e7 --- /dev/null +++ b/packages/entity/src/entities/setting_profiles.rs @@ -0,0 +1,55 @@ +//! `SeaORM` Entity, @generated by sea-orm-codegen 1.1.5 + +use sea_orm::entity::prelude::*; +use serde::{Deserialize, Serialize}; + +#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq, Serialize, Deserialize)] +#[sea_orm(table_name = "setting_profiles")] +#[onelauncher_macro::specta] +pub struct Model { + #[sea_orm(primary_key, auto_increment = false, column_type = "Text")] + pub name: String, + pub java_id: Option, + pub res_w: Option, + pub res_h: Option, + pub force_fullscreen: Option, + pub mem_max: Option, + #[sea_orm(column_type = "Text", nullable)] + pub launch_args: Option, + #[sea_orm(column_type = "Text", nullable)] + pub launch_env: Option, + #[sea_orm(column_type = "Text", nullable)] + pub hook_pre: Option, + #[sea_orm(column_type = "Text", nullable)] + pub hook_wrapper: Option, + #[sea_orm(column_type = "Text", nullable)] + pub hook_post: Option, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)] +pub enum Relation { + #[sea_orm(has_many = "super::clusters::Entity")] + Clusters, + #[sea_orm( + belongs_to = "super::java_versions::Entity", + from = "Column::JavaId", + to = "super::java_versions::Column::Id", + on_update = "NoAction", + on_delete = "NoAction" + )] + JavaVersions, +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Clusters.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::JavaVersions.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/packages/entity/src/lib.rs b/packages/entity/src/lib.rs new file mode 100644 index 00000000..39561cf5 --- /dev/null +++ b/packages/entity/src/lib.rs @@ -0,0 +1,2 @@ +mod entities; +pub use entities::*; \ No newline at end of file diff --git a/packages/gamemode/src/lib.rs b/packages/gamemode/src/lib.rs index 6e1253ce..2667fa2f 100644 --- a/packages/gamemode/src/lib.rs +++ b/packages/gamemode/src/lib.rs @@ -4,8 +4,8 @@ use libc::pid_t; use std::ffi::c_int; #[link(name = "stub", kind = "static")] -extern "C" { - fn gamemode_start_for_wrapper(pid: pid_t) -> c_int; +unsafe extern "C" { + unsafe fn gamemode_start_for_wrapper(pid: pid_t) -> c_int; } pub fn request_start_for_wrapper(pid: u32) -> Result<(), String> { diff --git a/packages/macros/Cargo.toml b/packages/macro/Cargo.toml similarity index 71% rename from packages/macros/Cargo.toml rename to packages/macro/Cargo.toml index 492bb79a..6c54c347 100644 --- a/packages/macros/Cargo.toml +++ b/packages/macro/Cargo.toml @@ -1,6 +1,6 @@ [package] -name = "onelauncher_macros" -description = "Debugger macros for OneLauncher" +name = "onelauncher_macro" +description = "Macros for OneLauncher" version = { workspace = true } license = { workspace = true } edition = { workspace = true } @@ -10,12 +10,15 @@ readme = { workspace = true } homepage = { workspace = true } authors = { workspace = true } -[lints] -workspace = true - [lib] +name = "onelauncher_macro" +path = "src/lib.rs" proc-macro = true +[features] +default = [] +specta = [] + [dependencies] syn = { workspace = true } quote = { workspace = true } diff --git a/packages/macro/src/lib.rs b/packages/macro/src/lib.rs new file mode 100644 index 00000000..081a24de --- /dev/null +++ b/packages/macro/src/lib.rs @@ -0,0 +1,52 @@ +use quote::quote; +use syn::{meta::ParseNestedMeta, parse_macro_input, Item, Result}; + +/// This macro is used to derive the `specta::Type` trait for the annotated item. +/// It's mainly meant for entity-generation with sea-orm-cli (it doesn't like commas in attributes) +///
+/// Expands to: +/// ``` +/// #[cfg_attr(feature = "specta", derive(specta::Type))] +/// ``` +#[proc_macro_attribute] +pub fn specta(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream { + let mut attrs = SpectaAttributes::default(); + let parser = syn::meta::parser(|meta| attrs.parse(meta)); + parse_macro_input!(attr with parser); + + let input = parse_macro_input!(item as Item); + + let specta_event_type = if attrs.with_event { + quote! { + #[cfg_attr(feature = "tauri", derive(tauri_specta::Event))] + } + } else { + quote! {} + }; + + let specta_type = quote! { + #[cfg_attr(feature = "specta", derive(specta::Type))] + }; + + let expanded = quote! { + #specta_event_type + #specta_type + #input + }; + + expanded.into() +} + +#[derive(Default)] +struct SpectaAttributes { + with_event: bool, +} + +impl SpectaAttributes { + fn parse(&mut self, meta: ParseNestedMeta) -> Result<()> { + if meta.path.is_ident("with_event") { + self.with_event = true; + } + Ok(()) + } +} \ No newline at end of file diff --git a/packages/macros/src/lib.rs b/packages/macros/src/lib.rs deleted file mode 100644 index 87a2687c..00000000 --- a/packages/macros/src/lib.rs +++ /dev/null @@ -1,34 +0,0 @@ -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, ItemFn}; - -/// Procedural macro that isolates a [`Box`] to ensure proper memory allocation in -/// debug environments. -#[proc_macro_attribute] -pub fn memory(_attr: TokenStream, item: TokenStream) -> TokenStream { - let input = parse_macro_input!(item as ItemFn); - - let attrs = &input.attrs; - let vis = &input.vis; - let sig = &input.sig; - let body = &input.block; - - #[cfg(debug_assertions)] - let result = quote! { - #(#attrs)* - #vis #sig { - Box::pin(async move { - #body - }).await - } - }; - #[cfg(not(debug_assertions))] - let result = quote! { - #(#attrs)* - #vis #sig { - #body - } - }; - - TokenStream::from(result) -} diff --git a/packages/migration/Cargo.toml b/packages/migration/Cargo.toml new file mode 100644 index 00000000..ec7161a1 --- /dev/null +++ b/packages/migration/Cargo.toml @@ -0,0 +1,21 @@ +[package] +name = "onelauncher_migration" +description = "Database migration for OneLauncher" +version = { workspace = true } +license = { workspace = true } +edition = { workspace = true } +repository = { workspace = true } +documentation = { workspace = true } +readme = { workspace = true } +homepage = { workspace = true } +authors = { workspace = true } +publish = false + +[lib] +name = "onelauncher_migration" +path = "src/lib.rs" + +[dependencies] +tokio = { workspace = true } +async-trait = { workspace = true } +sea-orm-migration = { workspace = true } diff --git a/packages/migration/README.md b/packages/migration/README.md new file mode 100644 index 00000000..3b438d89 --- /dev/null +++ b/packages/migration/README.md @@ -0,0 +1,41 @@ +# Running Migrator CLI + +- Generate a new migration file + ```sh + cargo run -- generate MIGRATION_NAME + ``` +- Apply all pending migrations + ```sh + cargo run + ``` + ```sh + cargo run -- up + ``` +- Apply first 10 pending migrations + ```sh + cargo run -- up -n 10 + ``` +- Rollback last applied migrations + ```sh + cargo run -- down + ``` +- Rollback last 10 applied migrations + ```sh + cargo run -- down -n 10 + ``` +- Drop all tables from the database, then reapply all migrations + ```sh + cargo run -- fresh + ``` +- Rollback all applied migrations, then reapply all migrations + ```sh + cargo run -- refresh + ``` +- Rollback all applied migrations + ```sh + cargo run -- reset + ``` +- Check the status of all migrations + ```sh + cargo run -- status + ``` diff --git a/packages/core_new/migrations/20250324184844_init.sql b/packages/migration/src/init.sql similarity index 91% rename from packages/core_new/migrations/20250324184844_init.sql rename to packages/migration/src/init.sql index 4a85fa7f..8b84d638 100644 --- a/packages/core_new/migrations/20250324184844_init.sql +++ b/packages/migration/src/init.sql @@ -32,7 +32,7 @@ create table setting_profiles ( java_id integer, res_w integer, res_h integer, - force_fullscreen integer, + force_fullscreen boolean, mem_max integer, launch_args text, launch_env text, @@ -40,7 +40,7 @@ create table setting_profiles ( hook_wrapper text, hook_post text, constraint setting_profiles_pk primary key (name), - constraint setting_profiles_java_versions_id_fk foreign key (java_id) references java_versions + constraint setting_profiles_java_versions_id_fk foreign key (java_id) references java_versions(id) ); create table clusters ( @@ -59,6 +59,6 @@ create table clusters ( linked_pack_id text, linked_pack_version integer, constraint clusters_pk primary key (path), - constraint clusters_cluster_groups_id_fk foreign key (group_id) references cluster_groups, - constraint clusters_setting_profiles_name_fk foreign key (setting_profile_name) references setting_profiles -); \ No newline at end of file + constraint clusters_cluster_groups_id_fk foreign key (group_id) references cluster_groups(id), + constraint clusters_setting_profiles_name_fk foreign key (setting_profile_name) references setting_profiles(name) +); diff --git a/packages/migration/src/lib.rs b/packages/migration/src/lib.rs new file mode 100644 index 00000000..2c605afb --- /dev/null +++ b/packages/migration/src/lib.rs @@ -0,0 +1,12 @@ +pub use sea_orm_migration::prelude::*; + +mod m20220101_000001_create_table; + +pub struct Migrator; + +#[async_trait::async_trait] +impl MigratorTrait for Migrator { + fn migrations() -> Vec> { + vec![Box::new(m20220101_000001_create_table::Migration)] + } +} diff --git a/packages/migration/src/m20220101_000001_create_table.rs b/packages/migration/src/m20220101_000001_create_table.rs new file mode 100644 index 00000000..e3ba6a3b --- /dev/null +++ b/packages/migration/src/m20220101_000001_create_table.rs @@ -0,0 +1,17 @@ +use sea_orm_migration::prelude::*; + +#[derive(DeriveMigrationName)] +pub struct Migration; + +#[async_trait::async_trait] +impl MigrationTrait for Migration { + async fn up(&self, manager: &SchemaManager) -> Result<(), DbErr> { + manager.get_connection().execute_unprepared(include_str!("./init.sql")).await?; + + Ok(()) + } + + async fn down(&self, _manager: &SchemaManager) -> Result<(), DbErr> { + unreachable!("Down migration is not supported for init migration"); + } +} diff --git a/packages/migration/src/main.rs b/packages/migration/src/main.rs new file mode 100644 index 00000000..f1c4f0a5 --- /dev/null +++ b/packages/migration/src/main.rs @@ -0,0 +1,6 @@ +use sea_orm_migration::prelude::*; + +#[tokio::main] +async fn main() { + cli::run_cli(onelauncher_migration::Migrator).await; +}