diff --git a/.github/workflows/check-generic.yml b/.github/workflows/check-generic.yml
new file mode 100644
index 000000000..56df6b1c9
--- /dev/null
+++ b/.github/workflows/check-generic.yml
@@ -0,0 +1,24 @@
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+
+env:
+ CARGO_TERM_COLOR: always
+ SQLX_OFFLINE: true
+
+jobs:
+ typos:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: crate-ci/typos@master
+
+ tombi:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: tombi-toml/setup-tombi@v1
+ - run: tombi lint
+ - run: tombi fmt --check
diff --git a/.github/workflows/check-rust.yml b/.github/workflows/check-rust.yml
new file mode 100644
index 000000000..97b08c255
--- /dev/null
+++ b/.github/workflows/check-rust.yml
@@ -0,0 +1,19 @@
+on:
+ pull_request:
+ push:
+ branches:
+ - master
+
+env:
+ CARGO_TERM_COLOR: always
+ SQLX_OFFLINE: true
+
+jobs:
+ shear:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: dtolnay/rust-toolchain@stable
+ - uses: cargo-bins/cargo-binstall@main
+ - run: cargo binstall --no-confirm cargo-shear
+ - run: cargo shear
diff --git a/Cargo.toml b/Cargo.toml
index 56f0201b1..8d42c3306 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,14 +1,14 @@
[workspace]
resolver = "2"
members = [
- "apps/app",
- "apps/app-playground",
- "apps/daedalus_client",
- "apps/labrinth",
- "packages/app-lib",
- "packages/ariadne",
- "packages/daedalus",
- "packages/path-util",
+ "apps/app",
+ "apps/app-playground",
+ "apps/daedalus_client",
+ "apps/labrinth",
+ "packages/app-lib",
+ "packages/ariadne",
+ "packages/daedalus",
+ "packages/path-util",
]
[workspace.package]
@@ -25,30 +25,34 @@ actix-web-prom = "0.10.0"
actix-ws = "0.3.0"
argon2 = { version = "0.5.3", features = ["std"] }
ariadne = { path = "packages/ariadne" }
-async_zip = "0.0.17"
async-compression = { version = "0.4.27", default-features = false }
async-recursion = "1.1.1"
async-stripe = { version = "0.41.0", default-features = false, features = [
- "runtime-tokio-hyper-rustls",
+ "runtime-tokio-hyper-rustls",
] }
async-trait = "0.1.88"
-async-tungstenite = { version = "0.30.0", default-features = false, features = ["futures-03-sink"] }
+async-tungstenite = { version = "0.30.0", default-features = false, features = [
+ "futures-03-sink",
+] }
async-walkdir = "2.1.0"
+async_zip = "0.0.17"
base64 = "0.22.1"
bitflags = "2.9.1"
bytemuck = "1.23.1"
bytes = "1.10.1"
-typed-path = "0.11.0"
censor = "0.3.0"
chardetng = "0.1.17"
chrono = "0.4.41"
-cidre = { version = "0.11.2", default-features = false, features = ["macos_15_0"] }
+cidre = { version = "0.11.2", default-features = false, features = [
+ "macos_15_0",
+] }
clap = "4.5.43"
clickhouse = "0.13.3"
+color-eyre = "0.6.5"
color-thief = "0.2.2"
console-subscriber = "0.4.1"
+const_format = "0.2.34"
daedalus = { path = "packages/daedalus" }
-path-util = { path = "packages/path-util" }
dashmap = "6.1.0"
data-url = "0.3.1"
deadpool-redis = "0.22.0"
@@ -61,6 +65,7 @@ dunce = "1.0.5"
either = "1.15.0"
encoding_rs = "0.8.35"
enumset = "1.1.7"
+eyre = "0.6.12"
flate2 = "1.1.2"
fs4 = { version = "0.13.1", default-features = false }
futures = { version = "0.3.31", default-features = false }
@@ -70,12 +75,11 @@ hex = "0.4.3"
hickory-resolver = "0.25.2"
hmac = "0.12.1"
hyper = "1.6.0"
-tracing-ecs = "0.5.0"
hyper-rustls = { version = "0.27.7", default-features = false, features = [
- "http1",
- "native-tokio",
- "ring",
- "tls12",
+ "http1",
+ "native-tokio",
+ "ring",
+ "tls12",
] }
hyper-util = "0.1.16"
iana-time-zone = "0.1.63"
@@ -86,15 +90,15 @@ itertools = "0.14.0"
jemalloc_pprof = "0.8.1"
json-patch = { version = "4.0.0", default-features = false }
lettre = { version = "0.11.18", default-features = false, features = [
- "builder",
- "hostname",
- "pool",
- "ring",
- "rustls",
- "rustls-native-certs",
- "tokio1-rustls",
- "smtp-transport",
- "tokio1",
+ "builder",
+ "hostname",
+ "pool",
+ "ring",
+ "rustls",
+ "rustls-native-certs",
+ "smtp-transport",
+ "tokio1",
+ "tokio1-rustls",
] }
maxminddb = "0.26.0"
meilisearch-sdk = { version = "0.29.1", default-features = false }
@@ -104,42 +108,45 @@ notify = { version = "8.2.0", default-features = false }
notify-debouncer-mini = { version = "0.7.0", default-features = false }
p256 = "0.13.2"
paste = "1.0.15"
+path-util = { path = "packages/path-util" }
phf = { version = "0.12.1", features = ["macros"] }
png = "0.17.16"
prometheus = "0.14.0"
quartz_nbt = "0.2.9"
quick-xml = "0.38.1"
-rand = "=0.8.5" # Locked on 0.8 until argon2 and p256 update to 0.9
-rand_chacha = "=0.3.1" # Locked on 0.3 until we can update rand to 0.9
+rand = "=0.8.5" # Locked on 0.8 until argon2 and p256 update to 0.9
+rand_chacha = "=0.3.1" # Locked on 0.3 until we can update rand to 0.9
redis = "0.32.4"
regex = "1.11.1"
reqwest = { version = "0.12.22", default-features = false }
rgb = "0.8.52"
-rust_decimal = { version = "1.37.2", features = ["serde-with-float", "serde-with-str"] }
+rust_decimal = { version = "1.37.2", features = [
+ "serde-with-float",
+ "serde-with-str",
+] }
rust_iso3166 = "0.1.14"
rust-s3 = { version = "0.35.1", default-features = false, features = [
- "fail-on-err",
- "tags",
- "tokio-rustls-tls",
+ "fail-on-err",
+ "tags",
+ "tokio-rustls-tls",
] }
rusty-money = "0.4.1"
sentry = { version = "0.42.0", default-features = false, features = [
- "backtrace",
- "contexts",
- "debug-images",
- "panic",
- "reqwest",
- "rustls",
+ "backtrace",
+ "contexts",
+ "debug-images",
+ "panic",
+ "reqwest",
+ "rustls",
] }
sentry-actix = "0.42.0"
-const_format = "0.2.34"
serde = "1.0.219"
serde_bytes = "0.11.17"
serde_cbor = "0.11.2"
serde_ini = "0.2.0"
serde_json = "1.0.142"
serde_with = "3.14.0"
-serde-xml-rs = "0.8.1" # Also an XML (de)serializer, consider dropping yaserde in favor of this
+serde-xml-rs = "0.8.1" # Also an XML (de)serializer, consider dropping yaserde in favor of this
sha1 = "0.10.6"
sha1_smol = { version = "1.0.1", features = ["std"] }
sha2 = "0.10.9"
@@ -156,8 +163,8 @@ tauri-plugin-opener = "2.4.0"
tauri-plugin-os = "2.3.0"
tauri-plugin-single-instance = "2.3.2"
tauri-plugin-updater = { version = "2.9.0", default-features = false, features = [
- "rustls-tls",
- "zip",
+ "rustls-tls",
+ "zip",
] }
tauri-plugin-window-state = "2.4.0"
tempfile = "3.20.0"
@@ -171,28 +178,28 @@ tokio-util = "0.7.16"
totp-rs = "5.7.0"
tracing = "0.1.41"
tracing-actix-web = { version = "0.7.19", default-features = false }
+tracing-ecs = "0.5.0"
tracing-error = "0.2.1"
tracing-subscriber = "0.3.19"
-eyre = "0.6.12"
-color-eyre = "0.6.5"
+typed-path = "0.11.0"
url = "2.5.4"
urlencoding = "2.1.3"
uuid = "1.17.0"
validator = "0.20.0"
webp = { version = "0.3.0", default-features = false }
+webview2-com = "0.38.0" # Should be updated in lockstep with wry
whoami = "1.6.0"
windows = "0.61.3"
windows-core = "0.61.2"
-webview2-com = "0.38.0" # Should be updated in lockstep with wry
winreg = "0.55.0"
woothee = "0.13.0"
yaserde = "0.12.0"
zbus = "5.9.0"
zip = { version = "4.3.0", default-features = false, features = [
- "bzip2",
- "deflate",
- "deflate64",
- "zstd",
+ "bzip2",
+ "deflate",
+ "deflate64",
+ "zstd",
] }
zxcvbn = "3.1.0"
@@ -230,18 +237,18 @@ todo = "warn"
unnested_or_patterns = "warn"
wildcard_dependencies = "warn"
+[profile.dev.package.sqlx-macros]
+opt-level = 3
+
# Optimize for speed and reduce size on release builds
[profile.release]
-opt-level = "s" # Optimize for binary size
-strip = true # Remove debug symbols
-lto = true # Enables link to optimizations
-panic = "abort" # Strip expensive panic clean-up logic
-codegen-units = 1 # Compile crates one after another so the compiler can optimize better
+opt-level = "s" # Optimize for binary size
+strip = true # Remove debug symbols
+lto = true # Enables link to optimizations
+panic = "abort" # Strip expensive panic clean-up logic
+codegen-units = 1 # Compile crates one after another so the compiler can optimize better
# Specific profile for labrinth production builds
[profile.release-labrinth]
inherits = "release"
-panic = "unwind" # Don't exit the whole app on panic in production
-
-[profile.dev.package.sqlx-macros]
-opt-level = 3
+panic = "unwind" # Don't exit the whole app on panic in production
diff --git a/_typos.toml b/_typos.toml
new file mode 100644
index 000000000..4dd9b96b8
--- /dev/null
+++ b/_typos.toml
@@ -0,0 +1,19 @@
+[files]
+extend-exclude = [
+ "**/src/locales/",
+ "apps/frontend/",
+ "patches/",
+ "packages/utils/",
+ "packages/ui/",
+ "packages/blog/",
+ # contains licenses like `CC-BY-ND-4.0`
+ "packages/moderation/src/data/stages/license.ts",
+ # contains payment card IDs like `IY1VMST1MOXS` which are flagged
+ "apps/labrinth/src/queue/payouts.rs",
+]
+
+[default.extend-words]
+# Terms Of Use in `tou-link`
+tou = "tou"
+# Google Ad Manager
+gam = "gam"
diff --git a/apps/app-playground/Cargo.toml b/apps/app-playground/Cargo.toml
index 691c9d3b7..c9e5caf47 100644
--- a/apps/app-playground/Cargo.toml
+++ b/apps/app-playground/Cargo.toml
@@ -1,14 +1,11 @@
[package]
name = "theseus_playground"
-version = "0.0.0"
edition.workspace = true
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
[dependencies]
+enumset = { workspace = true }
theseus = { workspace = true, features = ["cli"] }
tokio = { workspace = true, features = ["macros", "rt-multi-thread"] }
-enumset.workspace = true
[lints]
workspace = true
diff --git a/apps/app/Cargo.toml b/apps/app/Cargo.toml
index aadf8d9f2..4a07f2a1c 100644
--- a/apps/app/Cargo.toml
+++ b/apps/app/Cargo.toml
@@ -1,53 +1,51 @@
[package]
name = "theseus_gui"
-version = "1.0.0-local" # The actual version is set by the theseus-build workflow on tagging
-description = "The Modrinth App is a desktop application for managing your Minecraft mods"
-license = "GPL-3.0-only"
-repository = "https://github.com/modrinth/code/apps/app/"
+# The actual version is set by the theseus-build workflow on tagging
+version = "1.0.0-local"
edition.workspace = true
+description = "The Modrinth App is a desktop application for managing your Minecraft mods"
+repository = "https://github.com/modrinth/code/apps/app/"
+license = "GPL-3.0-only"
+
+[dependencies]
+chrono = { workspace = true }
+daedalus = { workspace = true }
+dashmap = { workspace = true }
+either = { workspace = true }
+enumset = { workspace = true, features = ["serde"] }
+hyper = { workspace = true, features = ["server"] }
+hyper-util = { workspace = true }
+native-dialog = { workspace = true }
+paste = { workspace = true }
+path-util = { workspace = true }
+serde = { workspace = true, features = ["derive"] }
+serde_json = { workspace = true }
+serde_with = { workspace = true }
+tauri = { workspace = true, features = [
+ "devtools",
+ "macos-private-api",
+ "protocol-asset",
+] }
+tauri-plugin-deep-link = { workspace = true }
+tauri-plugin-dialog = { workspace = true }
+tauri-plugin-http = { workspace = true }
+tauri-plugin-opener = { workspace = true }
+tauri-plugin-os = { workspace = true }
+tauri-plugin-single-instance = { workspace = true }
+tauri-plugin-updater = { workspace = true }
+tauri-plugin-window-state = { workspace = true }
+theseus = { workspace = true, features = ["tauri"] }
+thiserror = { workspace = true }
+tokio = { workspace = true, features = ["time"] }
+tracing = { workspace = true }
+tracing-error = { workspace = true }
+url = { workspace = true }
+urlencoding = { workspace = true }
+uuid = { workspace = true, features = ["serde", "v4"] }
[build-dependencies]
tauri-build = { workspace = true, features = ["codegen"] }
-[dependencies]
-theseus = { workspace = true, features = ["tauri"] }
-path-util.workspace = true
-
-serde_json.workspace = true
-serde = { workspace = true, features = ["derive"] }
-serde_with.workspace = true
-
-tauri = { workspace = true, features = ["devtools", "macos-private-api", "protocol-asset"] }
-tauri-plugin-deep-link.workspace = true
-tauri-plugin-dialog.workspace = true
-tauri-plugin-http.workspace = true
-tauri-plugin-opener.workspace = true
-tauri-plugin-os.workspace = true
-tauri-plugin-single-instance.workspace = true
-tauri-plugin-updater.workspace = true
-tauri-plugin-window-state.workspace = true
-
-tokio = { workspace = true, features = ["time"] }
-thiserror.workspace = true
-daedalus.workspace = true
-chrono.workspace = true
-either.workspace = true
-hyper = { workspace = true, features = ["server"] }
-hyper-util.workspace = true
-
-url.workspace = true
-urlencoding.workspace = true
-uuid = { workspace = true, features = ["serde", "v4"] }
-
-tracing.workspace = true
-tracing-error.workspace = true
-
-dashmap.workspace = true
-paste.workspace = true
-enumset = { workspace = true, features = ["serde"] }
-
-native-dialog.workspace = true
-
[target.'cfg(target_os = "linux")'.dependencies]
tauri-plugin-updater = { workspace = true, optional = true }
diff --git a/apps/app/src/api/oauth_utils/auth_code_reply/page.html b/apps/app/src/api/oauth_utils/auth_code_reply/page.html
index f0ccff4ad..53024a51a 100644
--- a/apps/app/src/api/oauth_utils/auth_code_reply/page.html
+++ b/apps/app/src/api/oauth_utils/auth_code_reply/page.html
@@ -1 +1 @@
-
Sign In - Modrinth App
+Sign In - Modrinth App
diff --git a/apps/app/src/api/profile.rs b/apps/app/src/api/profile.rs
index 93d388232..192c63880 100644
--- a/apps/app/src/api/profile.rs
+++ b/apps/app/src/api/profile.rs
@@ -272,7 +272,7 @@ pub struct EditProfile {
#[serde(
default,
skip_serializing_if = "Option::is_none",
- with = "::serde_with::rust::double_option"
+ with = "serde_with::rust::double_option"
)]
pub loader_version: Option