refactor: Base stuff done
This commit is contained in:
parent
5f4d4013b3
commit
2815c45409
32 changed files with 1181 additions and 180 deletions
436
Cargo.lock
generated
436
Cargo.lock
generated
|
|
@ -429,6 +429,15 @@ dependencies = [
|
|||
"system-deps",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atoi"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "atomic-waker"
|
||||
version = "1.1.2"
|
||||
|
|
@ -1124,6 +1133,15 @@ dependencies = [
|
|||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-queue"
|
||||
version = "0.3.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
|
|
@ -1340,42 +1358,6 @@ dependencies = [
|
|||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel"
|
||||
version = "2.2.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "470eb10efc8646313634c99bb1593f402a6434cbd86e266770c6e39219adb86a"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"diesel_derives",
|
||||
"libsqlite3-sys",
|
||||
"serde_json",
|
||||
"time",
|
||||
"uuid 0.8.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_derives"
|
||||
version = "2.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a93958254b70bea63b4187ff73d10180599d9d8d177071b7f91e6da4e0c0ad55"
|
||||
dependencies = [
|
||||
"diesel_table_macro_syntax",
|
||||
"dsl_auto_type",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diesel_table_macro_syntax"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "209c735641a413bc68c4923a9d6ad4bcb3ca306b794edaa7eb0b3228a99ffb25"
|
||||
dependencies = [
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.10.7"
|
||||
|
|
@ -1520,6 +1502,12 @@ 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"
|
||||
|
|
@ -1540,20 +1528,6 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dsl_auto_type"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "139ae9aca7527f85f26dd76483eb38533fd84bd571065da1739656ef71c5ff5b"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"either",
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "1.0.9"
|
||||
|
|
@ -1624,6 +1598,9 @@ name = "either"
|
|||
version = "1.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
|
|
@ -1739,6 +1716,17 @@ version = "3.3.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f"
|
||||
|
||||
[[package]]
|
||||
name = "etcetera"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"home",
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "event-listener"
|
||||
version = "5.3.1"
|
||||
|
|
@ -1854,6 +1842,8 @@ version = "0.11.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"spin",
|
||||
]
|
||||
|
||||
|
|
@ -1863,6 +1853,12 @@ version = "1.0.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
|
||||
|
||||
[[package]]
|
||||
name = "foreign-types"
|
||||
version = "0.5.0"
|
||||
|
|
@ -1960,6 +1956,17 @@ dependencies = [
|
|||
"futures-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-intrusive"
|
||||
version = "0.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"lock_api",
|
||||
"parking_lot",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "futures-io"
|
||||
version = "0.3.30"
|
||||
|
|
@ -2403,6 +2410,26 @@ dependencies = [
|
|||
"allocator-api2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.15.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
|
||||
dependencies = [
|
||||
"allocator-api2",
|
||||
"equivalent",
|
||||
"foldhash",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashlink"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
|
||||
dependencies = [
|
||||
"hashbrown 0.15.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
|
|
@ -3031,6 +3058,9 @@ name = "lazy_static"
|
|||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
dependencies = [
|
||||
"spin",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lebe"
|
||||
|
|
@ -3113,6 +3143,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libm"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libmimalloc-sys"
|
||||
version = "0.1.39"
|
||||
|
|
@ -3153,10 +3189,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libsqlite3-sys"
|
||||
version = "0.31.0"
|
||||
version = "0.30.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad8935b44e7c13394a179a438e0cebba0fe08fe01b54f152e29a93b5cf993fd4"
|
||||
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"pkg-config",
|
||||
"vcpkg",
|
||||
]
|
||||
|
|
@ -3272,6 +3309,16 @@ dependencies = [
|
|||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
version = "0.10.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"digest",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "md5"
|
||||
version = "0.7.0"
|
||||
|
|
@ -3548,6 +3595,23 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint-dig"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"lazy_static",
|
||||
"libm",
|
||||
"num-integer",
|
||||
"num-iter",
|
||||
"num-traits",
|
||||
"rand 0.8.5",
|
||||
"smallvec",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-conv"
|
||||
version = "0.1.0"
|
||||
|
|
@ -3574,6 +3638,17 @@ dependencies = [
|
|||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-iter"
|
||||
version = "0.1.45"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-rational"
|
||||
version = "0.4.2"
|
||||
|
|
@ -3592,6 +3667,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"libm",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3878,7 +3954,7 @@ dependencies = [
|
|||
"chrono",
|
||||
"dirs 5.0.1",
|
||||
"discord-rich-presence",
|
||||
"dotenvy",
|
||||
"dotenvy 0.15.7 (git+https://github.com/allan2/dotenvy/?rev=db0d6aa8fc8d1b0ddbfe94b5c833372e463eb1c5)",
|
||||
"flate2",
|
||||
"futures",
|
||||
"indicatif",
|
||||
|
|
@ -3981,14 +4057,16 @@ dependencies = [
|
|||
name = "onelauncher_new"
|
||||
version = "0.1.0-alpha.2"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-compression",
|
||||
"async-trait",
|
||||
"async_zip",
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"diesel",
|
||||
"dirs 5.0.1",
|
||||
"discord-rich-presence",
|
||||
"flate2",
|
||||
"dunce",
|
||||
"futures",
|
||||
"indicatif",
|
||||
"interpulse",
|
||||
|
|
@ -4007,6 +4085,7 @@ dependencies = [
|
|||
"sha1_smol",
|
||||
"sha2",
|
||||
"specta",
|
||||
"sqlx",
|
||||
"sysinfo",
|
||||
"tauri",
|
||||
"tauri-specta",
|
||||
|
|
@ -4395,6 +4474,17 @@ dependencies = [
|
|||
"futures-io",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs1"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
|
||||
dependencies = [
|
||||
"der",
|
||||
"pkcs8",
|
||||
"spki",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pkcs8"
|
||||
version = "0.10.2"
|
||||
|
|
@ -5018,6 +5108,26 @@ version = "1.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3582f63211428f83597b51b2ddb88e2a91a9d52d12831f9d08f5e624e8977422"
|
||||
|
||||
[[package]]
|
||||
name = "rsa"
|
||||
version = "0.9.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
|
||||
dependencies = [
|
||||
"const-oid",
|
||||
"digest",
|
||||
"num-bigint-dig",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
"pkcs1",
|
||||
"pkcs8",
|
||||
"rand_core 0.6.4",
|
||||
"signature",
|
||||
"spki",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-argon2"
|
||||
version = "1.0.0"
|
||||
|
|
@ -5505,6 +5615,9 @@ name = "smallvec"
|
|||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
|
|
@ -5643,6 +5756,201 @@ dependencies = [
|
|||
"der",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f"
|
||||
dependencies = [
|
||||
"sqlx-core",
|
||||
"sqlx-macros",
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-core"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"crossbeam-queue",
|
||||
"either",
|
||||
"event-listener",
|
||||
"futures-core",
|
||||
"futures-intrusive",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"hashbrown 0.15.2",
|
||||
"hashlink",
|
||||
"indexmap 2.5.0",
|
||||
"log",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid 1.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"sqlx-core",
|
||||
"sqlx-macros-core",
|
||||
"syn 2.0.87",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-macros-core"
|
||||
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)",
|
||||
"either",
|
||||
"heck 0.5.0",
|
||||
"hex",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"sqlx-core",
|
||||
"sqlx-mysql",
|
||||
"sqlx-postgres",
|
||||
"sqlx-sqlite",
|
||||
"syn 2.0.87",
|
||||
"tempfile",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-mysql"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.6.0",
|
||||
"byteorder",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"digest",
|
||||
"dotenvy 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"either",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-io",
|
||||
"futures-util",
|
||||
"generic-array",
|
||||
"hex",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"itoa 1.0.11",
|
||||
"log",
|
||||
"md-5",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"percent-encoding",
|
||||
"rand 0.8.5",
|
||||
"rsa",
|
||||
"serde",
|
||||
"sha1",
|
||||
"sha2",
|
||||
"smallvec",
|
||||
"sqlx-core",
|
||||
"stringprep",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"uuid 1.10.0",
|
||||
"whoami",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-postgres"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"base64 0.22.1",
|
||||
"bitflags 2.6.0",
|
||||
"byteorder",
|
||||
"chrono",
|
||||
"crc",
|
||||
"dotenvy 0.15.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"etcetera",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"hex",
|
||||
"hkdf",
|
||||
"hmac",
|
||||
"home",
|
||||
"itoa 1.0.11",
|
||||
"log",
|
||||
"md-5",
|
||||
"memchr",
|
||||
"once_cell",
|
||||
"rand 0.8.5",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sha2",
|
||||
"smallvec",
|
||||
"sqlx-core",
|
||||
"stringprep",
|
||||
"thiserror 2.0.12",
|
||||
"tracing",
|
||||
"uuid 1.10.0",
|
||||
"whoami",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sqlx-sqlite"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540"
|
||||
dependencies = [
|
||||
"atoi",
|
||||
"chrono",
|
||||
"flume",
|
||||
"futures-channel",
|
||||
"futures-core",
|
||||
"futures-executor",
|
||||
"futures-intrusive",
|
||||
"futures-util",
|
||||
"libsqlite3-sys",
|
||||
"log",
|
||||
"percent-encoding",
|
||||
"serde",
|
||||
"serde_urlencoded",
|
||||
"sqlx-core",
|
||||
"tracing",
|
||||
"url",
|
||||
"uuid 1.10.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stable_deref_trait"
|
||||
version = "1.2.0"
|
||||
|
|
@ -5681,6 +5989,17 @@ dependencies = [
|
|||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stringprep"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
|
||||
dependencies = [
|
||||
"unicode-bidi",
|
||||
"unicode-normalization",
|
||||
"unicode-properties",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stronghold-derive"
|
||||
version = "1.0.0"
|
||||
|
|
@ -6636,6 +6955,7 @@ version = "0.1.40"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
|
||||
dependencies = [
|
||||
"log",
|
||||
"pin-project-lite",
|
||||
"tracing-attributes",
|
||||
"tracing-core",
|
||||
|
|
@ -6861,6 +7181,12 @@ dependencies = [
|
|||
"tinyvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicode-properties"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.12.0"
|
||||
|
|
|
|||
|
|
@ -126,10 +126,12 @@ md5 = { version = "0.7.0" }
|
|||
bytes = { version = "1.7" }
|
||||
|
||||
# # ============= UTILITY ============= # #
|
||||
diesel = { version = "2.2.0", features = [
|
||||
sqlx = { version = "0.8", features = [
|
||||
"runtime-tokio",
|
||||
"sqlite",
|
||||
"returning_clauses_for_sqlite_3_35",
|
||||
"serde_json",
|
||||
"macros",
|
||||
"derive",
|
||||
"migrate",
|
||||
"uuid",
|
||||
"chrono"
|
||||
] }
|
||||
|
|
@ -149,6 +151,7 @@ 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" }
|
||||
|
|
|
|||
|
|
@ -14,10 +14,16 @@ authors = { workspace = true }
|
|||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
tauri = [ "dep:tauri", "dep:tauri-specta", "specta" ]
|
||||
default = [ "cli" ]
|
||||
tauri = [
|
||||
"dep:tauri",
|
||||
"dep:tauri-specta",
|
||||
"specta",
|
||||
"gui"
|
||||
]
|
||||
specta = [ "dep:specta" ]
|
||||
cli = [ "dep:indicatif" ]
|
||||
gui = []
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
|
@ -39,12 +45,13 @@ serde_repr = { workspace = true }
|
|||
serde_with = { workspace = true }
|
||||
|
||||
# utils
|
||||
diesel = { workspace = true }
|
||||
sqlx = { workspace = true }
|
||||
tokio = { workspace = true }
|
||||
tokio-stream = { workspace = true }
|
||||
futures = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
reqwest = { workspace = true }
|
||||
regex = { workspace = true }
|
||||
|
|
@ -53,6 +60,7 @@ whoami = { workspace = true }
|
|||
lazy_static = { workspace = true }
|
||||
rand = { workspace = true }
|
||||
url = { workspace = true }
|
||||
async-trait = { workspace = true }
|
||||
|
||||
# integration
|
||||
discord-rich-presence = { workspace = true }
|
||||
|
|
@ -69,7 +77,8 @@ async_zip = { workspace = true }
|
|||
dirs = { workspace = true }
|
||||
bytes = { workspace = true }
|
||||
base64 = { workspace = true }
|
||||
flate2 = { workspace = true }
|
||||
async-compression = { workspace = true }
|
||||
dunce = { workspace = true }
|
||||
|
||||
# features[tauri]
|
||||
tauri = { workspace = true, optional = true }
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
# For documentation on how to configure this file,
|
||||
# see https://diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/schema.rs"
|
||||
custom_type_derives = [ "diesel::query_builder::QueryId", "Clone" ]
|
||||
|
||||
|
||||
|
|
@ -1 +0,0 @@
|
|||
-- this is the init migration, it is not reversible
|
||||
|
|
@ -13,6 +13,6 @@
|
|||
"scripts": {
|
||||
"cargo": "cargo",
|
||||
"binary": "cargo run --bin",
|
||||
"diesel": "diesel"
|
||||
"sqlx": "sqlx"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
14
packages/core_new/sqlx_guide.md
Normal file
14
packages/core_new/sqlx_guide.md
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# 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"
|
||||
```
|
||||
37
packages/core_new/src/api/ingress.rs
Normal file
37
packages/core_new/src/api/ingress.rs
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
use crate::{store::{ingress::{IngressId, IngressType}, State}, LauncherResult};
|
||||
|
||||
pub async fn init_ingress(
|
||||
ingress_type: IngressType,
|
||||
message: &str,
|
||||
total: f64,
|
||||
) -> LauncherResult<IngressId> {
|
||||
let state = State::get().await?;
|
||||
let processor = &state.ingress_processor;
|
||||
|
||||
let id = processor.create(ingress_type, message.to_string(), total).await?;
|
||||
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
pub async fn send_ingress(id: IngressId) -> LauncherResult<()> {
|
||||
let state = State::get().await?;
|
||||
let processor = &state.ingress_processor;
|
||||
|
||||
processor.send(id.0).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn update_ingress(id: IngressId, current: f64) -> LauncherResult<()> {
|
||||
let state = State::get().await?;
|
||||
let processor = &state.ingress_processor;
|
||||
|
||||
processor.update(id.0, current).await
|
||||
}
|
||||
|
||||
pub async fn finish_ingress(id: IngressId) -> LauncherResult<()> {
|
||||
let state = State::get().await?;
|
||||
let processor = &state.ingress_processor;
|
||||
|
||||
processor.finish(id.0).await?;
|
||||
Ok(())
|
||||
}
|
||||
2
packages/core_new/src/api/mod.rs
Normal file
2
packages/core_new/src/api/mod.rs
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
pub mod ingress;
|
||||
pub mod proxy;
|
||||
59
packages/core_new/src/api/proxy/message.rs
Normal file
59
packages/core_new/src/api/proxy/message.rs
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
use serde::Serialize;
|
||||
|
||||
#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct MessagePayload {
|
||||
pub level: MessageLevel,
|
||||
pub message: String,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub enum MessageLevel {
|
||||
Info,
|
||||
Warning,
|
||||
Error,
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! send_warning {
|
||||
($($message:tt)*) => {{
|
||||
tokio::spawn(async move {
|
||||
let _ = match $crate::store::proxy::ProxyState::get() {
|
||||
Ok(proxy) => {
|
||||
let payload = $crate::api::proxy::message::MessagePayload {
|
||||
level: $crate::api::proxy::message::MessageLevel::Warning,
|
||||
message: format!($($message)*),
|
||||
};
|
||||
let _ = proxy.send_message(payload).await;
|
||||
},
|
||||
Err(err) => {
|
||||
tracing::warn!($($message)*);
|
||||
tracing::warn!("failed to send warning: {}", err);
|
||||
},
|
||||
};
|
||||
})
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! send_error {
|
||||
($($message:tt)*) => {{
|
||||
tokio::spawn(async move {
|
||||
let _ = match $crate::store::proxy::ProxyState::get() {
|
||||
Ok(proxy) => {
|
||||
let payload = $crate::api::proxy::message::MessagePayload {
|
||||
level: $crate::api::proxy::message::MessageLevel::Error,
|
||||
message: format!($($message)*),
|
||||
};
|
||||
let _ = proxy.send_message(payload).await;
|
||||
},
|
||||
Err(err) => {
|
||||
tracing::error!($($message)*);
|
||||
tracing::error!("failed to send error: {}", err);
|
||||
},
|
||||
};
|
||||
})
|
||||
}};
|
||||
}
|
||||
20
packages/core_new/src/api/proxy/mod.rs
Normal file
20
packages/core_new/src/api/proxy/mod.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
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<()>;
|
||||
}
|
||||
|
||||
45
packages/core_new/src/api/proxy/proxy_cli.rs
Normal file
45
packages/core_new/src/api/proxy/proxy_cli.rs
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use indicatif::ProgressBar;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::{store::{ingress::IngressPayload, State}, LauncherResult};
|
||||
|
||||
use super::LauncherProxy;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ProxyCli {
|
||||
ingress_feeds: RwLock<HashMap<Uuid, ProgressBar>>,
|
||||
}
|
||||
|
||||
impl ProxyCli {
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl LauncherProxy for ProxyCli {
|
||||
|
||||
async fn send_ingress(&self, ingress: IngressPayload) -> LauncherResult<()> {
|
||||
let feeds = self.ingress_feeds.write().await;
|
||||
|
||||
if let Some(progress) = feeds.get(&ingress.id) {
|
||||
// progress.set_position(ingress.percent as u64);
|
||||
// TODO: customize progress bar
|
||||
} else {
|
||||
let progress = ProgressBar::new(ingress.total as u64);
|
||||
progress.set_message(ingress.message.clone());
|
||||
progress.set_position(0);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn send_message(&self, message: crate::api::proxy::message::MessagePayload) -> LauncherResult<()> {
|
||||
println!("[{:?}] {:?}", message.level, message.message);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
}
|
||||
63
packages/core_new/src/api/proxy/proxy_tauri.rs
Normal file
63
packages/core_new/src/api/proxy/proxy_tauri.rs
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
use tauri::{AppHandle, Emitter, Manager};
|
||||
use tauri_specta::Event;
|
||||
use tracing::{error, warn};
|
||||
|
||||
use crate::{store::ingress::IngressPayload, LauncherResult};
|
||||
|
||||
use super::{message::{MessageLevel, MessagePayload}, LauncherProxy};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProxyTauri {
|
||||
handle: AppHandle,
|
||||
}
|
||||
|
||||
impl ProxyTauri {
|
||||
#[must_use]
|
||||
pub const fn new(handle: AppHandle) -> Self {
|
||||
Self {
|
||||
handle
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl LauncherProxy for ProxyTauri {
|
||||
async fn send_ingress(&self, ingress: IngressPayload) -> LauncherResult<()> {
|
||||
self.handle
|
||||
.emit(IngressPayload::NAME, ingress)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
async fn send_message(&self, message: MessagePayload) -> LauncherResult<()> {
|
||||
match message.level {
|
||||
MessageLevel::Info => {},
|
||||
MessageLevel::Warning => warn!("{}", message.message),
|
||||
MessageLevel::Error => error!("{}", message.message),
|
||||
};
|
||||
|
||||
self.handle
|
||||
.emit(MessagePayload::NAME, message)
|
||||
.map_err(Into::into)
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
fn hide_main_window(&self) -> LauncherResult<()> {
|
||||
if let Some(window) = self.handle.get_webview_window("main") {
|
||||
Ok(window.hide()?)
|
||||
} else {
|
||||
warn!("main window not found");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument]
|
||||
fn show_main_window(&self) -> LauncherResult<()> {
|
||||
if let Some(window) = self.handle.get_webview_window("main") {
|
||||
Ok(window.show()?)
|
||||
} else {
|
||||
warn!("main window not found");
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
use onelauncher_new::io::Dirs;
|
||||
use onelauncher_new::store::Dirs;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
//! **`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.
|
||||
|
|
|
|||
|
|
@ -1,7 +1,24 @@
|
|||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum LauncherError {
|
||||
#[error(transparent)]
|
||||
DirError(#[from] crate::io::DirectoryError),
|
||||
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<T> = Result<T, LauncherError>;
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
mod dirs;
|
||||
|
||||
pub use dirs::*;
|
||||
|
|
@ -1,16 +1,10 @@
|
|||
// Private (accessible by crate only) modules
|
||||
|
||||
// Modules which are not re-exported
|
||||
pub mod io;
|
||||
pub mod constants;
|
||||
pub mod schema;
|
||||
pub mod utils;
|
||||
pub mod store;
|
||||
pub mod api;
|
||||
|
||||
// Modules which are re-exported
|
||||
mod state;
|
||||
mod error;
|
||||
mod logger;
|
||||
|
||||
// Re-exported modules
|
||||
pub use state::State;
|
||||
pub use error::*;
|
||||
pub use error::{LauncherResult, LauncherError};
|
||||
pub use logger::start_logger;
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
cluster_groups (id) {
|
||||
id -> Integer,
|
||||
name -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
clusters (path) {
|
||||
path -> Text,
|
||||
created_at -> Integer,
|
||||
updated_at -> Integer,
|
||||
group_id -> Nullable<Integer>,
|
||||
name -> Text,
|
||||
mc_version -> Text,
|
||||
mc_loader -> Text,
|
||||
mc_loader_version -> Nullable<Text>,
|
||||
last_played -> Nullable<Integer>,
|
||||
overall_played -> Nullable<Integer>,
|
||||
icon_url -> Nullable<Text>,
|
||||
setting_profile_name -> Nullable<Text>,
|
||||
linked_pack_id -> Nullable<Text>,
|
||||
linked_pack_version -> Nullable<Integer>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
java_versions (id) {
|
||||
id -> Integer,
|
||||
major_version -> Integer,
|
||||
display_name -> Text,
|
||||
absolute_path -> Text,
|
||||
full_version -> Text,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
packages (file_name, type_id) {
|
||||
file_name -> Text,
|
||||
display_name -> Text,
|
||||
display_version -> Text,
|
||||
type_id -> Integer,
|
||||
provider_id -> Integer,
|
||||
provider_version -> Text,
|
||||
mc_versions -> Text,
|
||||
mc_loader -> Text,
|
||||
hash -> Text,
|
||||
icon_url -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
setting_profiles (name) {
|
||||
name -> Text,
|
||||
java_id -> Nullable<Integer>,
|
||||
res_w -> Nullable<Integer>,
|
||||
res_h -> Nullable<Integer>,
|
||||
force_fullscreen -> Nullable<Integer>,
|
||||
mem_max -> Nullable<Integer>,
|
||||
launch_args -> Nullable<Text>,
|
||||
launch_env -> Nullable<Text>,
|
||||
hook_pre -> Nullable<Text>,
|
||||
hook_wrapper -> Nullable<Text>,
|
||||
hook_post -> Nullable<Text>,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(clusters -> cluster_groups (group_id));
|
||||
diesel::joinable!(clusters -> setting_profiles (setting_profile_name));
|
||||
diesel::joinable!(setting_profiles -> java_versions (java_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
cluster_groups,
|
||||
clusters,
|
||||
java_versions,
|
||||
packages,
|
||||
setting_profiles,
|
||||
);
|
||||
32
packages/core_new/src/store/db.rs
Normal file
32
packages/core_new/src/store/db.rs
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
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<SqlitePool> {
|
||||
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)
|
||||
}
|
||||
|
||||
pub async fn create_pool() -> LauncherResult<SqlitePool> {
|
||||
let path = Dirs::get().await?.db_file();
|
||||
create_pool_from_path(path).await
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ use std::path::PathBuf;
|
|||
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
use crate::{constants, LauncherResult};
|
||||
use crate::{constants, utils, LauncherResult};
|
||||
|
||||
/// The static [`OnceCell<RwLock<Dirs>>`] for storing the global directory state.
|
||||
/// Should be initialized as soon as possible (preferably before logging)
|
||||
|
|
@ -20,7 +20,7 @@ impl Dirs {
|
|||
}
|
||||
|
||||
fn initialize() -> LauncherResult<Self> {
|
||||
let base_dir = env_path("LAUNCHER_DIR")
|
||||
let base_dir = utils::io::env_path("LAUNCHER_DIR")
|
||||
.or_else(|| Some(dirs::data_dir()?.join(constants::NAME)))
|
||||
.ok_or(DirectoryError::BaseDir)?;
|
||||
|
||||
|
|
@ -41,11 +41,20 @@ impl Dirs {
|
|||
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]
|
||||
|
|
@ -85,6 +94,3 @@ pub enum DirectoryError {
|
|||
BaseDir,
|
||||
}
|
||||
|
||||
pub fn env_path(name: &str) -> Option<PathBuf> {
|
||||
std::env::var_os(name).map(PathBuf::from)
|
||||
}
|
||||
144
packages/core_new/src/store/ingress.rs
Normal file
144
packages/core_new/src/store/ingress.rs
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use serde::Serialize;
|
||||
use tokio::sync::RwLock;
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::LauncherResult;
|
||||
|
||||
use super::{proxy::ProxyState, State};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct IngressProcessor {
|
||||
ingress_feeds: RwLock<HashMap<Uuid, Ingress>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
pub enum IngressError {
|
||||
#[error("ingress not found")]
|
||||
NotFound,
|
||||
}
|
||||
|
||||
impl IngressProcessor {
|
||||
#[must_use]
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
ingress_feeds: RwLock::new(HashMap::new()),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn create(&self, ingress_type: IngressType, message: String, total: f64) -> LauncherResult<IngressId> {
|
||||
let mut feeds = self.ingress_feeds.write().await;
|
||||
|
||||
let uuid = Uuid::new_v4();
|
||||
let ingress = Ingress {
|
||||
id: IngressId(uuid),
|
||||
message,
|
||||
ingress_type,
|
||||
total,
|
||||
current: 0.0,
|
||||
last_sent: 0.0,
|
||||
};
|
||||
|
||||
feeds.insert(uuid, ingress);
|
||||
|
||||
self.send(uuid).await?;
|
||||
|
||||
Ok(IngressId(uuid))
|
||||
}
|
||||
|
||||
pub async fn update(&self, id: Uuid, current: f64) -> LauncherResult<()> {
|
||||
let mut feeds = self.ingress_feeds.write().await;
|
||||
let ingress = feeds.get_mut(&id).ok_or_else(|| IngressError::NotFound)?;
|
||||
ingress.current = current;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn send(&self, id: Uuid) -> LauncherResult<()> {
|
||||
let feeds = self.ingress_feeds.read().await;
|
||||
let ingress = feeds.get(&id).ok_or_else(|| IngressError::NotFound)?;
|
||||
|
||||
let proxy = ProxyState::get()?;
|
||||
proxy.send_ingress(IngressPayload {
|
||||
id: ingress.id.0,
|
||||
message: ingress.message.clone(),
|
||||
ingress_type: ingress.ingress_type.clone(),
|
||||
percent: Some(ingress.current / ingress.total),
|
||||
total: ingress.total,
|
||||
}).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn finish(&self, uuid: Uuid) -> LauncherResult<Ingress> {
|
||||
let mut feeds = self.ingress_feeds.write().await;
|
||||
Ok(feeds.remove(&uuid).ok_or_else(|| IngressError::NotFound)?)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct IngressId(pub Uuid);
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Ingress {
|
||||
pub id: IngressId,
|
||||
pub message: String,
|
||||
pub ingress_type: IngressType,
|
||||
pub total: f64,
|
||||
pub current: f64,
|
||||
pub last_sent: f64,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "tauri", derive(tauri_specta::Event))]
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub struct IngressPayload {
|
||||
pub id: Uuid,
|
||||
pub message: String,
|
||||
pub ingress_type: IngressType,
|
||||
pub percent: Option<f64>,
|
||||
pub total: f64,
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "specta", derive(specta::Type))]
|
||||
#[derive(Serialize, Debug, Clone)]
|
||||
pub enum IngressType {
|
||||
Download {
|
||||
file_name: String,
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for IngressId {
|
||||
#[clippy::has_significant_drop]
|
||||
fn drop(&mut self) {
|
||||
let ingress_uuid = self.0;
|
||||
tokio::spawn(async move {
|
||||
let result: LauncherResult<()> = async {
|
||||
let state = State::get().await?;
|
||||
let processor = &state.ingress_processor;
|
||||
|
||||
let ingress = processor.finish(ingress_uuid).await?;
|
||||
|
||||
let proxy = ProxyState::get()?;
|
||||
|
||||
proxy.send_ingress(IngressPayload {
|
||||
id: ingress.id.0,
|
||||
message: "Completed".into(),
|
||||
ingress_type: ingress.ingress_type,
|
||||
percent: None,
|
||||
total: ingress.total,
|
||||
}).await?;
|
||||
|
||||
tracing::trace!("exited at {}% for ingress {:?}", ingress.current / ingress.total * 100.0, ingress_uuid);
|
||||
|
||||
Ok(())
|
||||
}.await;
|
||||
|
||||
if let Err(e) = result {
|
||||
tracing::error!("failed to finish ingress: {:?}", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
10
packages/core_new/src/store/mod.rs
Normal file
10
packages/core_new/src/store/mod.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
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::*;
|
||||
40
packages/core_new/src/store/proxy.rs
Normal file
40
packages/core_new/src/store/proxy.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
use std::{ops::Deref, sync::Arc};
|
||||
|
||||
use anyhow::anyhow;
|
||||
use tokio::sync::OnceCell;
|
||||
|
||||
use crate::{api::proxy::LauncherProxy, LauncherResult};
|
||||
|
||||
static PROXY_STATE: OnceCell<Arc<ProxyState>> = OnceCell::const_new();
|
||||
|
||||
pub struct ProxyState {
|
||||
inner: Box<dyn LauncherProxy>,
|
||||
}
|
||||
|
||||
impl Deref for ProxyState {
|
||||
type Target = Box<dyn LauncherProxy>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl ProxyState {
|
||||
pub async fn initialize(proxy: Box<dyn LauncherProxy>) -> LauncherResult<Arc<Self>> {
|
||||
PROXY_STATE
|
||||
.get_or_try_init(|| async {
|
||||
Ok(Arc::new(Self {
|
||||
inner: proxy,
|
||||
}))
|
||||
})
|
||||
.await
|
||||
.cloned()
|
||||
}
|
||||
|
||||
pub fn get() -> LauncherResult<Arc<Self>> {
|
||||
Ok(PROXY_STATE
|
||||
.get()
|
||||
.ok_or_else(|| anyhow!("proxy state not initialized"))
|
||||
.cloned()?)
|
||||
}
|
||||
}
|
||||
74
packages/core_new/src/store/settings.rs
Normal file
74
packages/core_new/src/store/settings.rs
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
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 {
|
||||
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<Self> {
|
||||
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<usize>,
|
||||
pub res_w: Option<usize>,
|
||||
pub res_h: Option<usize>,
|
||||
pub force_fullscreen: Option<bool>,
|
||||
pub mem_max: Option<usize>,
|
||||
pub launch_args: Option<String>,
|
||||
pub launch_env: Option<String>,
|
||||
pub hook_pre: Option<String>,
|
||||
pub hook_wrapper: Option<String>,
|
||||
pub hook_post: Option<String>,
|
||||
}
|
||||
|
|
@ -1,14 +1,19 @@
|
|||
use std::sync::Arc;
|
||||
|
||||
use sqlx::SqlitePool;
|
||||
use tokio::sync::{OnceCell, RwLock};
|
||||
|
||||
use crate::LauncherResult;
|
||||
|
||||
use super::{ingress::IngressProcessor, Settings};
|
||||
|
||||
/// The static [`OnceCell<RwLock<State>>`] for storing the global runtime launcher state.
|
||||
static LAUNCHER_STATE: OnceCell<RwLock<State>> = OnceCell::const_new();
|
||||
|
||||
pub struct State {
|
||||
|
||||
pub ingress_processor: IngressProcessor,
|
||||
pub settings: Settings,
|
||||
pub db: SqlitePool,
|
||||
}
|
||||
|
||||
impl State {
|
||||
|
|
@ -32,9 +37,19 @@ impl State {
|
|||
.await)
|
||||
}
|
||||
|
||||
async fn initialize() -> LauncherResult<RwLock<Self>> {
|
||||
Ok(RwLock::new(Self {
|
||||
pub fn initialized() -> bool {
|
||||
LAUNCHER_STATE.initialized()
|
||||
}
|
||||
|
||||
async fn initialize() -> LauncherResult<RwLock<Self>> {
|
||||
let ingress_processor = IngressProcessor::new();
|
||||
let settings = Settings::new().await;
|
||||
let db = super::db::create_pool().await?;
|
||||
|
||||
Ok(RwLock::new(Self {
|
||||
ingress_processor,
|
||||
settings,
|
||||
db,
|
||||
}))
|
||||
}
|
||||
}
|
||||
185
packages/core_new/src/utils/io.rs
Normal file
185
packages/core_new/src/utils/io.rs
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
use async_compression::tokio::bufread::GzipDecoder;
|
||||
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("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),
|
||||
}
|
||||
|
||||
impl<P: AsRef<std::path::Path>> From<(P, std::io::Error)> for IOError {
|
||||
fn from((path, source): (P, std::io::Error)) -> Self {
|
||||
Self::IOErrorWrapper {
|
||||
source,
|
||||
path: path.as_ref().to_string_lossy().to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, thiserror::Error)]
|
||||
#[error("received a non UTF-8 path: <lossy_path='{}'>", .0.to_string_lossy())]
|
||||
pub struct NonUtf8PathError(pub Box<std::path::Path>);
|
||||
|
||||
/// Attempts to parse a path taken from an environment variable. Returns `None` if the variable is not set.
|
||||
pub fn env_path(name: &str) -> Option<std::path::PathBuf> {
|
||||
std::env::var_os(name).map(std::path::PathBuf::from)
|
||||
}
|
||||
|
||||
/// An OS specific wrapper of [`std::fs::canonicalize`], but on Windows it outputs the most compatible form of a path instead of UNC.
|
||||
pub fn canonicalize(path: impl AsRef<std::path::Path>) -> Result<std::path::PathBuf, IOError> {
|
||||
let path = path.as_ref();
|
||||
dunce::canonicalize(path).map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a stream over the entries within a directory.
|
||||
pub async fn read_dir(path: impl AsRef<std::path::Path>) -> Result<tokio::fs::ReadDir, IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::read_dir(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a directory if they are missing.
|
||||
pub async fn create_dir(path: impl AsRef<std::path::Path>) -> Result<(), IOError> {
|
||||
let path = path.as_ref();
|
||||
if path.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
tokio::fs::create_dir(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Recursively creates a directory and all of its parent components if they are missing.
|
||||
pub async fn create_dir_all(path: impl AsRef<std::path::Path>) -> Result<(), IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::create_dir_all(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Removes a directory at this path, after removing all its contents. Use carefully!
|
||||
pub async fn remove_dir_all(path: impl AsRef<std::path::Path>) -> Result<(), IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::remove_dir_all(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Creates a future which will open a gzip compressed file for reading and read the entire contents into a string and return said string.
|
||||
pub async fn read_gz_to_string(path: impl AsRef<std::path::Path>) -> Result<String, IOError> {
|
||||
let mut f = tokio::fs::File::open(path).await?;
|
||||
let mut buf = vec![];
|
||||
f.read_to_end(&mut buf).await?;
|
||||
|
||||
let mut decoder = GzipDecoder::new(buf.as_slice());
|
||||
let mut dst = String::new();
|
||||
decoder.read_to_string(&mut dst).await?;
|
||||
|
||||
Ok(dst)
|
||||
}
|
||||
|
||||
/// Creates a future which will open a file for reading and read the entire contents into a string and return said string.
|
||||
pub async fn read_to_string(path: impl AsRef<std::path::Path>) -> Result<String, IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::read_to_string(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Reads the entire contents of a file into a bytes vector.
|
||||
pub async fn read(path: impl AsRef<std::path::Path>) -> Result<Vec<u8>, IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::read(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Asynchrously write to a tempfile that is then transferred to an official [`AsRef<Path>`].
|
||||
pub async fn write(
|
||||
path: impl AsRef<std::path::Path>,
|
||||
data: impl AsRef<[u8]>,
|
||||
) -> Result<(), IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::write(path, data)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Renames a file or directory to a new name, replacing the original file if `to` already exists.
|
||||
pub async fn rename(
|
||||
from: impl AsRef<std::path::Path>,
|
||||
to: impl AsRef<std::path::Path>,
|
||||
) -> Result<(), IOError> {
|
||||
let from = from.as_ref();
|
||||
let to = to.as_ref();
|
||||
tokio::fs::rename(from, to)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: from.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Copies the contents of one file to another. This function will also copy the permission bits of the original file to the destination file. This function will overwrite the contents of to.
|
||||
pub async fn copy(
|
||||
from: impl AsRef<std::path::Path>,
|
||||
to: impl AsRef<std::path::Path>,
|
||||
) -> Result<u64, IOError> {
|
||||
let from = from.as_ref();
|
||||
let to = to.as_ref();
|
||||
tokio::fs::copy(from, to)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: from.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
/// Removes a file from the filesystem.
|
||||
pub async fn remove_file(path: impl AsRef<std::path::Path>) -> Result<(), IOError> {
|
||||
let path = path.as_ref();
|
||||
tokio::fs::remove_file(path)
|
||||
.await
|
||||
.map_err(|e| IOError::IOErrorWrapper {
|
||||
source: e,
|
||||
path: path.to_string_lossy().to_string(),
|
||||
})
|
||||
}
|
||||
1
packages/core_new/src/utils/mod.rs
Normal file
1
packages/core_new/src/utils/mod.rs
Normal file
|
|
@ -0,0 +1 @@
|
|||
pub mod io;
|
||||
|
|
@ -199,7 +199,7 @@ https://learn.microsoft.com/windows/package-manager/winget/
|
|||
Write-Host
|
||||
Write-Host 'Installing Rust tools...' -ForegroundColor Yellow
|
||||
cargo install cargo-watch
|
||||
cargo install diesel_cli --no-default-features --features sqlite
|
||||
cargo install sqlx-cli
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Exit-WithError 'Failed to install Rust tools'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -183,10 +183,8 @@ esac
|
|||
# installs cargo-watch for development purposes
|
||||
if [ "${CI:-}" != "true" ]; then
|
||||
echo "installing rust tools..."
|
||||
_tools="cargo-watch"
|
||||
_tools="cargo-watch sqlx-cli"
|
||||
echo "$_tools" | xargs cargo install
|
||||
|
||||
cargo install diesel_cli --no-default-features --features sqlite
|
||||
fi
|
||||
|
||||
echo 'your machine has been setup for onelauncher development!'
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue