From 7956b8cecde79c19eb6a8dc8a3fde60527128602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-X=2E=20T=2E?= Date: Fri, 4 Sep 2026 16:35:26 -0400 Subject: [PATCH 1/6] feat(hosting frontend): suspended server files download --- .../src/pages/settings/billing/index.vue | 39 ++++---- .../src/modules/archon/servers/v1.ts | 18 ++++ .../api-client/src/modules/archon/types.ts | 14 +++ .../api-client/src/modules/kyros/files/v1.ts | 30 ++++++ .../api-client/src/modules/kyros/types.ts | 4 + .../src/components/servers/ServerListing.vue | 25 +++-- packages/ui/src/composables/index.ts | 2 +- packages/ui/src/composables/server-backup.ts | 54 ----------- .../ui/src/composables/server-download.ts | 93 +++++++++++++++++++ .../layouts/wrapped/hosting/manage/index.vue | 36 +++---- packages/ui/src/locales/de-CH/index.json | 3 - packages/ui/src/locales/de-DE/index.json | 3 - packages/ui/src/locales/en-US/index.json | 4 +- packages/ui/src/locales/es-419/index.json | 3 - packages/ui/src/locales/es-ES/index.json | 3 - packages/ui/src/locales/fr-FR/index.json | 3 - packages/ui/src/locales/hu-HU/index.json | 3 - packages/ui/src/locales/it-IT/index.json | 3 - packages/ui/src/locales/ja-JP/index.json | 3 - packages/ui/src/locales/ko-KR/index.json | 3 - packages/ui/src/locales/ms-MY/index.json | 3 - packages/ui/src/locales/nl-NL/index.json | 3 - packages/ui/src/locales/pl-PL/index.json | 3 - packages/ui/src/locales/pt-BR/index.json | 3 - packages/ui/src/locales/ru-RU/index.json | 3 - packages/ui/src/locales/sr-CS/index.json | 3 - packages/ui/src/locales/sv-SE/index.json | 3 - packages/ui/src/locales/tr-TR/index.json | 3 - packages/ui/src/locales/uk-UA/index.json | 3 - packages/ui/src/locales/vi-VN/index.json | 3 - packages/ui/src/locales/zh-CN/index.json | 3 - packages/ui/src/locales/zh-TW/index.json | 3 - .../stories/servers/AuditLogTable.stories.ts | 3 + .../stories/servers/ServerListing.stories.ts | 16 ++-- packages/ui/src/utils/index.ts | 1 + packages/ui/src/utils/server-billing.ts | 12 +++ 36 files changed, 234 insertions(+), 180 deletions(-) delete mode 100644 packages/ui/src/composables/server-backup.ts create mode 100644 packages/ui/src/composables/server-download.ts create mode 100644 packages/ui/src/utils/server-billing.ts diff --git a/apps/frontend/src/pages/settings/billing/index.vue b/apps/frontend/src/pages/settings/billing/index.vue index a993e5246e..1cc532d96d 100644 --- a/apps/frontend/src/pages/settings/billing/index.vue +++ b/apps/frontend/src/pages/settings/billing/index.vue @@ -291,7 +291,7 @@ v-bind="subscription.serverInfo" :pending-change="getPendingChange(subscription)" :cancellation-date="getCancellationDate(subscription)" - :on-download-backup="getBackupDownloadForServer(subscription.serverInfo)" + :on-download-world="getWorldDownload(subscription.serverInfo, serverFullList)" />

@@ -508,11 +508,7 @@ {{ formatMessage(messages.upgrade) }}

- +
+ + +
@@ -95,17 +106,27 @@ :description="formatMessage(messages.emptyDescription)" > (() => [ const client = injectModrinthClient() const queryClient = useQueryClient() const { server, worldId, busyReasons } = injectModrinthServerContext() +const { downloadWorldFiles } = useServerWorldDownload() +const isDownloadingFiles = ref(false) + +async function downloadFiles() { + const node = server.value.node + const currentWorldId = worldId.value + if (!node || !currentWorldId || isDownloadingFiles.value) return + + isDownloadingFiles.value = true + try { + await downloadWorldFiles(node.instance, currentWorldId) + } finally { + isDownloadingFiles.value = false + } +} const props = defineProps<{ isServerRunning: boolean diff --git a/packages/ui/src/layouts/wrapped/hosting/manage/index.vue b/packages/ui/src/layouts/wrapped/hosting/manage/index.vue index 231e251569..ba1891ca23 100644 --- a/packages/ui/src/layouts/wrapped/hosting/manage/index.vue +++ b/packages/ui/src/layouts/wrapped/hosting/manage/index.vue @@ -188,7 +188,7 @@ :cancellation-date="serverBillingMap.get(server.server_id)?.cancellationDate" :is-provisioning="serverBillingMap.get(server.server_id)?.isProvisioning" :on-resubscribe="serverBillingMap.get(server.server_id)?.onResubscribe" - :on-download-world="getWorldDownload(server, serverFullList)" + :on-download-world="getWorldDownload(server.server_id, serverFullList)" />
@@ -216,7 +216,6 @@ v-for="server in sharedFilteredData.filter((s) => !s.is_medal)" :key="`shared-${server.server_id}`" v-bind="server" - :on-download-world="getWorldDownload(server, serverFullList)" />
@@ -565,9 +564,11 @@ function sortServers(array: Archon.Servers.v0.Server[]): Archon.Servers.v0.Serve } function shouldShowServer(server: Archon.Servers.v0.Server): boolean { - if (server.status !== 'suspended') return true + if (server.status !== 'suspended' || server.suspension_reason !== 'cancelled') return true + const cancellationDate = serverBillingMap.value.get(server.server_id)?.cancellationDate + if (!cancellationDate || !serverFullList.value) return true return ( - !!serverBillingMap.value.get(server.server_id)?.onResubscribe || + isWithinServerResubscribeWindow(cancellationDate) || hasAvailableWorldDownload(server.server_id, serverFullList.value) ) } diff --git a/packages/ui/src/utils/common-messages.ts b/packages/ui/src/utils/common-messages.ts index 314863039e..d53deb76c5 100644 --- a/packages/ui/src/utils/common-messages.ts +++ b/packages/ui/src/utils/common-messages.ts @@ -124,6 +124,10 @@ export const commonMessages = defineMessages({ id: 'button.download', defaultMessage: 'Download', }, + downloadFilesButton: { + id: 'button.download-files', + defaultMessage: 'Download files', + }, downloadingButton: { id: 'button.downloading', defaultMessage: 'Downloading', From fcf1f8ec1f6cb74bfd30ccec868f1bd505cd29ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-X=2E=20T=2E?= Date: Fri, 4 Sep 2026 17:20:57 -0400 Subject: [PATCH 3/6] lint --- .../instructions/i18n-convert.instructions.md | 24 +-- AGENTS.md | 3 + Cargo.toml | 128 +++++++-------- _typos.toml | 24 +-- apps/app/Cargo.toml | 12 +- apps/app/capabilities/plugins.json | 4 +- apps/daedalus_client/Cargo.toml | 18 +-- apps/docs/src/styles/modrinth.css | 5 +- .../copilot.data.migration.ask2agent.xml | 10 +- apps/labrinth/.idea/labrinth.iml | 20 +-- apps/labrinth/.idea/modules.xml | 17 +- apps/labrinth/.idea/vcs.xml | 10 +- apps/labrinth/Cargo.toml | 55 ++++--- apps/labrinth/src/api_v2_description.md | 19 ++- apps/labrinth/src/api_v3_description.md | 1 - docker-compose.yml | 27 +--- package.json | 150 +++++++++--------- packages/app-lib/Cargo.toml | 64 ++++---- packages/ui/src/composables/index.ts | 2 +- turbo.jsonc | 21 +-- 20 files changed, 301 insertions(+), 313 deletions(-) diff --git a/.github/instructions/i18n-convert.instructions.md b/.github/instructions/i18n-convert.instructions.md index 91786f4fe3..aa1f5a53f3 100644 --- a/.github/instructions/i18n-convert.instructions.md +++ b/.github/instructions/i18n-convert.instructions.md @@ -33,24 +33,24 @@ Please follow these rules precisely: "By creating an account, you agree to our Terms and Privacy Policy." - Render rich-text messages with `` from `@modrinth/ui` using named slots: - - + + - For simple emphasis: `'Welcome to Modrinth!'` with a slot: - For more complex child handling, use `normalizeChildren` from `@modrinth/ui`: 5. Formatting in templates diff --git a/AGENTS.md b/AGENTS.md index c962748cbc..4e46b24039 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -70,12 +70,14 @@ Each project may have its own file with detailed instructions: ## Code Guidelines ### Comments + - DO NOT use "heading" comments like: `=== Helper methods ===`. - Use doc comments, but avoid inline comments unless ABSOLUTELY necessary for clarity. Code should aim to be self documenting! ## Bash Guidelines ### Output handling + - DO NOT pipe output through `head`, `tail`, `less`, or `more` - NEVER use `| head -n X` or `| tail -n X` to truncate output - IMPORTANT: Run commands directly without pipes when possible @@ -83,6 +85,7 @@ Each project may have its own file with detailed instructions: - ALWAYS read the full output — never pipe through filters ### General + - Do not create new non-source code files (e.g. Bash scripts, SQL scripts) unless explicitly prompted to - For Frontend, when doing lint checks, only use the `prepr` commands, do not use `typecheck` or `tsc` etc. - Types in `@modrinth/utils` are considered highly outdated, if a component needs them, check if you can switch said component to use types from `packages/api-client` diff --git a/Cargo.toml b/Cargo.toml index 99b0c562a5..168f5d6c35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,22 @@ [workspace] resolver = "2" members = [ - "apps/app", - "apps/app-playground", - "apps/daedalus_client", - "apps/labrinth", - "packages/app-lib", - "packages/ariadne", - "packages/component-derive", - "packages/daedalus", - "packages/modrinth-content-management", - "packages/modrinth-log", - "packages/modrinth-maxmind", - "packages/modrinth-util", - "packages/neverbounce", - "packages/path-util", - "packages/serde-binhum", - "packages/xredis", + "apps/app", + "apps/app-playground", + "apps/daedalus_client", + "apps/labrinth", + "packages/app-lib", + "packages/ariadne", + "packages/component-derive", + "packages/daedalus", + "packages/modrinth-content-management", + "packages/modrinth-log", + "packages/modrinth-maxmind", + "packages/modrinth-util", + "packages/neverbounce", + "packages/path-util", + "packages/serde-binhum", + "packages/xredis", ] [workspace.package] @@ -39,16 +39,16 @@ ariadne = { path = "packages/ariadne" } async-minecraft-ping = { path = "packages/async-minecraft-ping" } 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.89" async-tungstenite = { version = "0.31.0", default-features = false, features = ["futures-03-sink"] } async-walkdir = "2.1.0" async_zip = "0.0.18" aws-sdk-s3 = { version = "=1.122.0", default-features = false, features = [ - "default-https-client", - "rt-tokio", - "rustls", + "default-https-client", + "rt-tokio", + "rustls", ] } base64 = "0.22.1" bitflags = "2.9.4" @@ -98,10 +98,10 @@ hmac = "0.12.1" httpdate = "1.0.3" hyper = "1.7.0" hyper-rustls = { version = "0.27.7", default-features = false, features = [ - "aws-lc-rs", - "http1", - "native-tokio", - "tls12", + "aws-lc-rs", + "http1", + "native-tokio", + "tls12", ] } hyper-util = "0.1.17" iana-time-zone = "0.1.64" @@ -113,21 +113,21 @@ jemalloc_pprof = "0.8.1" json-patch = { version = "4.1.0", default-features = false } json5 = "1.3.1" lettre = { version = "0.11.19", default-features = false, features = [ - "aws-lc-rs", - "builder", - "hostname", - "pool", - "rustls", - "rustls-native-certs", - "smtp-transport", - "tokio1", - "tokio1-rustls", + "aws-lc-rs", + "builder", + "hostname", + "pool", + "rustls", + "rustls-native-certs", + "smtp-transport", + "tokio1", + "tokio1-rustls", ] } lz4_flex = { version = "0.11.5", default-features = false, features = [ - "checked-decode", - "safe-decode", - "safe-encode", - "std", + "checked-decode", + "safe-decode", + "safe-encode", + "std", ] } maxminddb = "0.26.0" modrinth-content-management = { path = "packages/modrinth-content-management" } @@ -153,8 +153,8 @@ prometheus = "0.14.0" quartz_nbt = "0.2.9" quick-xml = "0.38.3" quote = { version = "1.0" } -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 rdkafka = { version = "0.36.2", features = ["cmake-build"] } redis = "1.4.1" regex = "1.12.2" @@ -163,21 +163,21 @@ rgb = "0.8.52" rust_decimal = { version = "1.39.0", features = ["serde-with-float", "serde-with-str"] } rust_iso3166 = "0.1.14" rust-s3 = { version = "0.37.0", default-features = false, features = [ - "fail-on-err", - "tags", - "tokio-rustls-tls", + "fail-on-err", + "tags", + "tokio-rustls-tls", ] } rustls = "0.23.32" rusty-money = "0.4.1" scalar_api_reference = { version = "0.2.2", default-features = false } secrecy = "0.10.3" sentry = { version = "0.45.0", default-features = false, features = [ - "backtrace", - "contexts", - "debug-images", - "panic", - "reqwest", - "rustls", + "backtrace", + "contexts", + "debug-images", + "panic", + "reqwest", + "rustls", ] } serde = "1.0.228" serde-binhum = { path = "packages/serde-binhum" } @@ -208,8 +208,8 @@ tauri-plugin-opener = "2.5.0" tauri-plugin-os = "2.3.1" tauri-plugin-single-instance = "2.3.4" tauri-plugin-updater = { git = "https://github.com/modrinth/plugins-workspace", rev = "0d30f2aa28ec668ce187d527da1c475da3c01cbc", default-features = false, features = [ - "rustls-tls", - "zip", + "rustls-tls", + "zip", ] } tauri-plugin-window-state = "2.4.0" tempfile = "3.23.0" @@ -237,20 +237,20 @@ validator = "0.20.0" webauthn-rs = "0.5.5" webauthn-rs-proto = "0.5.5" webp = { version = "0.3.1", default-features = false } -webview2-com = "0.38.0" # Should be updated in lockstep with wry +webview2-com = "0.38.0" # Should be updated in lockstep with wry whoami = "1.6.1" -windows = "=0.61.3" # Locked on 0.61 until we can update windows-core to 0.62 -windows-core = "=0.61.2" # Locked on 0.61 until webview2-com updates to 0.62 +windows = "=0.61.3" # Locked on 0.61 until we can update windows-core to 0.62 +windows-core = "=0.61.2" # Locked on 0.61 until webview2-com updates to 0.62 winreg = "0.55.0" woothee = "0.13.0" xredis = { path = "packages/xredis" } yaserde = "0.12.0" zbus = "5.11.0" zip = { version = "6.0.0", default-features = false, features = [ - "bzip2", - "deflate", - "deflate64", - "zstd", + "bzip2", + "deflate", + "deflate64", + "zstd", ] } zxcvbn = "3.1.0" @@ -297,15 +297,15 @@ 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 +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 # Specific profile for labrinth production builds [profile.release-labrinth] inherits = "release" opt-level = 2 -strip = false # Keep debug symbols for Sentry -lto = "thin" # Enable LTO but keep compile times reasonable -panic = "unwind" # Don't exit the whole app on panic in production +strip = false # Keep debug symbols for Sentry +lto = "thin" # Enable LTO but keep compile times reasonable +panic = "unwind" # Don't exit the whole app on panic in production diff --git a/_typos.toml b/_typos.toml index 944064d355..58e28588bc 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1,21 +1,21 @@ [files] extend-exclude = [ - "**/src/locales/", - "apps/frontend/", - "patches/", - "packages/utils/", - "packages/ui/", - "packages/blog/", + "**/src/locales/", + "apps/frontend/", + "patches/", + "packages/utils/", + "packages/ui/", + "packages/blog/", ] [default] extend-ignore-re = [ - # Ignore lines that end with `// typos:ignore` - "(?Rm)^.*(#|//)\\s*typos:ignore$", - # Ignore the line after `// typos:ignore`: - "(#|//)\\s*typos:ignore\\n.*", - # Ignore blocks between `// typos:off` and `// typos:on` - "(?s)(#|//)\\s*typos:off.*?\\n\\s*(#|//)\\s*typos:on", + # Ignore lines that end with `// typos:ignore` + "(?Rm)^.*(#|//)\\s*typos:ignore$", + # Ignore the line after `// typos:ignore`: + "(#|//)\\s*typos:ignore\\n.*", + # Ignore blocks between `// typos:off` and `// typos:on` + "(?s)(#|//)\\s*typos:off.*?\\n\\s*(#|//)\\s*typos:on", ] [default.extend-words] diff --git a/apps/app/Cargo.toml b/apps/app/Cargo.toml index 5e7115cad3..a41284eb6c 100644 --- a/apps/app/Cargo.toml +++ b/apps/app/Cargo.toml @@ -61,12 +61,12 @@ windows-core.workspace = true [target."cfg(windows)".dependencies.windows] workspace = true features = [ - "Win32_Foundation", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_System_Com", - "Win32_UI_Shell", - "Win32_UI_WindowsAndMessaging", + "Win32_Foundation", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_System_Com", + "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", ] [features] diff --git a/apps/app/capabilities/plugins.json b/apps/app/capabilities/plugins.json index 875968d902..65d1441028 100644 --- a/apps/app/capabilities/plugins.json +++ b/apps/app/capabilities/plugins.json @@ -2,9 +2,7 @@ "identifier": "plugins", "description": "", "local": true, - "windows": [ - "main" - ], + "windows": ["main"], "permissions": [ "dialog:allow-open", "dialog:allow-confirm", diff --git a/apps/daedalus_client/Cargo.toml b/apps/daedalus_client/Cargo.toml index 080fab4f3e..b6b40664fb 100644 --- a/apps/daedalus_client/Cargo.toml +++ b/apps/daedalus_client/Cargo.toml @@ -5,12 +5,12 @@ edition.workspace = true [dependencies] async_zip = { workspace = true, features = [ - "bzip2", - "chrono", - "deflate", - "deflate64", - "tokio-fs", - "zstd", + "bzip2", + "chrono", + "deflate", + "deflate64", + "tokio-fs", + "zstd", ] } bytes = { workspace = true } chrono = { workspace = true, features = ["serde"] } @@ -21,11 +21,7 @@ futures = { workspace = true } indexmap = { workspace = true, features = ["serde"] } itertools = { workspace = true } quick-xml = { workspace = true } -reqwest = { workspace = true, features = [ - "json", - "rustls-tls-native-roots", - "stream", -] } +reqwest = { workspace = true, features = ["json", "rustls-tls-native-roots", "stream"] } rust-s3 = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/apps/docs/src/styles/modrinth.css b/apps/docs/src/styles/modrinth.css index 4f149c26a7..b61c7fbe4c 100644 --- a/apps/docs/src/styles/modrinth.css +++ b/apps/docs/src/styles/modrinth.css @@ -2,8 +2,9 @@ ::backdrop, :root[data-theme='light'], [data-theme='light'] ::backdrop { - --sl-font-system: Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, - Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + --sl-font-system: + Inter, -apple-system, BlinkMacSystemFont, Segoe UI, Oxygen, Ubuntu, Roboto, Cantarell, + Fira Sans, Droid Sans, Helvetica Neue, sans-serif; --sl-color-white: var(--color-contrast); /* “white” */ --sl-color-gray-1: var(--color-base); diff --git a/apps/labrinth/.idea/copilot.data.migration.ask2agent.xml b/apps/labrinth/.idea/copilot.data.migration.ask2agent.xml index 1f2ea11e7f..e38d36d4cf 100644 --- a/apps/labrinth/.idea/copilot.data.migration.ask2agent.xml +++ b/apps/labrinth/.idea/copilot.data.migration.ask2agent.xml @@ -1,6 +1,6 @@ - + - - - \ No newline at end of file + + + diff --git a/apps/labrinth/.idea/labrinth.iml b/apps/labrinth/.idea/labrinth.iml index b5c2fdebc2..227b39cde8 100644 --- a/apps/labrinth/.idea/labrinth.iml +++ b/apps/labrinth/.idea/labrinth.iml @@ -1,11 +1,11 @@ - + - - - - - - - - - \ No newline at end of file + + + + + + + + + diff --git a/apps/labrinth/.idea/modules.xml b/apps/labrinth/.idea/modules.xml index 0d8b557a85..d2ffc4e5b0 100644 --- a/apps/labrinth/.idea/modules.xml +++ b/apps/labrinth/.idea/modules.xml @@ -1,8 +1,11 @@ - + - - - - - - \ No newline at end of file + + + + + + diff --git a/apps/labrinth/.idea/vcs.xml b/apps/labrinth/.idea/vcs.xml index b2bdec2d71..c0e6d24e42 100644 --- a/apps/labrinth/.idea/vcs.xml +++ b/apps/labrinth/.idea/vcs.xml @@ -1,6 +1,6 @@ - + - - - - \ No newline at end of file + + + + diff --git a/apps/labrinth/Cargo.toml b/apps/labrinth/Cargo.toml index d94e808ed4..e76823ee69 100644 --- a/apps/labrinth/Cargo.toml +++ b/apps/labrinth/Cargo.toml @@ -51,21 +51,21 @@ hmac = { workspace = true } hyper-rustls = { workspace = true } hyper-util = { workspace = true } image = { workspace = true, features = [ - "avif", - "bmp", - "dds", - "exr", - "ff", - "gif", - "hdr", - "ico", - "jpeg", - "png", - "pnm", - "qoi", - "tga", - "tiff", - "webp", + "avif", + "bmp", + "dds", + "exr", + "ff", + "gif", + "hdr", + "ico", + "jpeg", + "png", + "pnm", + "qoi", + "tga", + "tiff", + "webp", ] } itertools = { workspace = true } json-patch = { workspace = true } @@ -101,14 +101,14 @@ sha2 = { workspace = true } smallvec = { workspace = true } spdx = { workspace = true, features = ["text"] } sqlx = { workspace = true, features = [ - "chrono", - "json", - "macros", - "migrate", - "postgres", - "runtime-tokio", - "rust_decimal", - "tls-rustls-aws-lc-rs", + "chrono", + "json", + "macros", + "migrate", + "postgres", + "runtime-tokio", + "rust_decimal", + "tls-rustls-aws-lc-rs", ] } sqlx-tracing = { workspace = true, features = ["postgres"] } strum = { workspace = true, features = ["derive"] } @@ -123,7 +123,10 @@ urlencoding = { workspace = true } utoipa = { workspace = true, features = ["url"] } uuid = { workspace = true, features = ["fast-rng", "serde", "v4", "v7"] } validator = { workspace = true, features = ["derive"] } -webauthn-rs = { workspace = true, features = ["conditional-ui", "danger-allow-state-serialisation"] } +webauthn-rs = { workspace = true, features = [ + "conditional-ui", + "danger-allow-state-serialisation", +] } webauthn-rs-proto = { workspace = true } webp = { workspace = true } woothee = { workspace = true } @@ -145,8 +148,8 @@ iana-time-zone = { workspace = true } jemalloc_pprof = { workspace = true, features = ["flamegraph"] } tikv-jemalloc-ctl = { workspace = true, features = ["stats"] } tikv-jemallocator = { workspace = true, features = [ - "profiling", - "unprefixed_malloc_on_supported_platforms", + "profiling", + "unprefixed_malloc_on_supported_platforms", ] } [features] diff --git a/apps/labrinth/src/api_v2_description.md b/apps/labrinth/src/api_v2_description.md index 551b6e80b7..8e620789c4 100644 --- a/apps/labrinth/src/api_v2_description.md +++ b/apps/labrinth/src/api_v2_description.md @@ -2,10 +2,12 @@ > API v2 is Modrinth's current, official API. It is the recommended API for integrations and applications and will receive long-term support. ## Authentication + This API has two options for authentication: personal access tokens and [OAuth2](https://en.wikipedia.org/wiki/OAuth). All tokens are tied to a Modrinth user and use the `Authorization` header of the request. Example: + ``` Authorization: mrp_RNtLRSPmGj2pd1v1ubi52nX7TJJM9sznrmwhAuj511oe4t1jAqAQ3D6Wc8Ic ``` @@ -13,6 +15,7 @@ Authorization: mrp_RNtLRSPmGj2pd1v1ubi52nX7TJJM9sznrmwhAuj511oe4t1jAqAQ3D6Wc8Ic > [!tip] You do not need a token for most requests. > > Generally speaking, only the following types of requests require a token: +> > - those which create data (such as version creation) > - those which modify data (such as editing a project) > - those which access private data (such as draft projects, notifications, emails, and payout data) @@ -24,18 +27,22 @@ Please note that certain scopes and requests cannot be completed with a personal For example, deleting a user account can only be done through Modrinth's frontend. ### Personal access tokens + Personal access tokens (PATs) can be generated from [the user settings](https://modrinth.com/settings/account). ### GitHub tokens + For backwards compatibility purposes, some types of GitHub tokens also work for authenticating a user with Modrinth's API, granting all scopes. **We urge any application still using GitHub tokens to start using personal access tokens for security and reliability purposes.** ## Cross-Origin Resource Sharing + This API features Cross-Origin Resource Sharing (CORS) implemented in compliance with the [W3C spec](https://www.w3.org/TR/cors/). This allows for cross-domain communication from the browser. All responses have a wildcard same-origin which makes them completely public and accessible to everyone, including any code on any site. ## Identifiers + The majority of items you can interact with in the API have a unique eight-digit base62 ID. Projects, versions, users, threads, teams, and reports all use this same way of identifying themselves. Version files use the sha1 or sha512 file hashes as identifiers. @@ -45,7 +52,9 @@ While unique IDs are constant, slugs and usernames can change at any moment. If you want to store something in the long term, it is recommended to use the unique ID. ## Ratelimits + The API has a ratelimit defined per IP. Limits and remaining amounts are given in the response headers. + - `X-Ratelimit-Limit`: the maximum number of requests that can be made in a minute - `X-Ratelimit-Remaining`: the number of requests remaining in the current ratelimit window - `X-Ratelimit-Reset`: the time in seconds until the ratelimit window resets @@ -57,20 +66,24 @@ The ratelimit is currently 300 requests per minute per IP. If your application i Higher rate limits are granted only in very rare cases. If you believe your use case requires an exception, please [contact us](mailto:support@modrinth.com). ## User Agents + To access the Modrinth API, you **must** use provide a uniquely-identifying `User-Agent` header. Providing a user agent that only identifies your HTTP client library (such as "okhttp/4.9.3") increases the likelihood that we will block your traffic. It is recommended, but not required, to include contact information in your user agent. This allows us to contact you if we would like a change in your application's behavior without having to block your traffic. + - Bad: `User-Agent: okhttp/4.9.3` - Good: `User-Agent: project_name` - Better: `User-Agent: github_username/project_name/1.56.0` - Best: `User-Agent: github_username/project_name/1.56.0 (launcher.com)` or `User-Agent: github_username/project_name/1.56.0 (contact@launcher.com)` ## Versioning + Modrinth follows a simple pattern for its API versioning. In the event of a breaking API change, the API version in the URL path is bumped, and migration steps will be published below. ### Migrations + Inside the following spoiler, you will be able to find all changes between versions of the Modrinth API, accompanied by tips and a guide to migrate applications to newer versions.
API v1 to API v2 @@ -82,12 +95,12 @@ These bullet points cover most changes in the v2 API, but please note that field - New search facet: `project_type` - Alphabetical sort removed (it didn't work and is not possible due to limits in MeiliSearch) - New search fields: `project_type`, `gallery` - - The gallery field is an array of URLs to images that are part of the project's gallery + - The gallery field is an array of URLs to images that are part of the project's gallery - The gallery is a new feature which allows the user to upload images showcasing their mod to the CDN which will be displayed on their mod page - Internal change: Any project file uploaded to Modrinth is now validated to make sure it's a valid Minecraft mod, Modpack, etc. - - For example, a Forge 1.17 mod with a JAR not containing a mods.toml will not be allowed to be uploaded to Modrinth + - For example, a Forge 1.17 mod with a JAR not containing a mods.toml will not be allowed to be uploaded to Modrinth - In project creation, projects may not upload a mod with no versions to review, however they can be saved as a draft - - Similarly, for version creation, a version may not be uploaded without any files + - Similarly, for version creation, a version may not be uploaded without any files - Donation URLs have been enabled - New project status: `archived`. Projects with this status do not appear in search - Tags (such as categories, loaders) now have icons (SVGs) and specific project types attached diff --git a/apps/labrinth/src/api_v3_description.md b/apps/labrinth/src/api_v3_description.md index 2e2449615b..9b0e577c5e 100644 --- a/apps/labrinth/src/api_v3_description.md +++ b/apps/labrinth/src/api_v3_description.md @@ -3,6 +3,5 @@ > > **Please do not use this API in production. It will be deprecated in the future.** - > [!tip] > You're probably looking for [Modrinth's public API v2](/docs?api=v2) diff --git a/docker-compose.yml b/docker-compose.yml index d33ff19224..cf0c6cc4e5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -57,10 +57,7 @@ services: hard: -1 healthcheck: test: - [ - 'CMD-SHELL', - 'curl --fail http://localhost:9200/_cluster/health?wait_for_status=yellow', - ] + ['CMD-SHELL', 'curl --fail http://localhost:9200/_cluster/health?wait_for_status=yellow'] interval: 5s timeout: 5s retries: 30 @@ -89,10 +86,7 @@ services: hard: -1 healthcheck: test: - [ - 'CMD-SHELL', - 'curl --fail http://localhost:9200/_cluster/health?wait_for_status=yellow', - ] + ['CMD-SHELL', 'curl --fail http://localhost:9200/_cluster/health?wait_for_status=yellow'] interval: 5s timeout: 5s retries: 30 @@ -121,10 +115,7 @@ services: hard: -1 healthcheck: test: - [ - 'CMD-SHELL', - 'curl --fail http://localhost:9200/_cluster/health?wait_for_status=yellow', - ] + ['CMD-SHELL', 'curl --fail http://localhost:9200/_cluster/health?wait_for_status=yellow'] interval: 5s timeout: 5s retries: 30 @@ -432,14 +423,7 @@ services: environment: MP_ENABLE_SPAMASSASSIN: postmark healthcheck: - test: - [ - 'CMD', - 'wget', - '-q', - '-O/dev/null', - 'http://localhost:8025/api/v1/info', - ] + test: ['CMD', 'wget', '-q', '-O/dev/null', 'http://localhost:8025/api/v1/info'] interval: 3s timeout: 5s retries: 3 @@ -526,8 +510,7 @@ services: LABRINTH_ENDPOINT: http://host.docker.internal:8000/_internal/delphi/ingest LABRINTH_ADMIN_KEY: feedbeef healthcheck: - test: - ['CMD', 'wget', '-q', '-O/dev/null', 'http://localhost:59999/health'] + test: ['CMD', 'wget', '-q', '-O/dev/null', 'http://localhost:59999/health'] interval: 3s timeout: 5s retries: 3 diff --git a/package.json b/package.json index 4e84fe7f1d..facb60a521 100644 --- a/package.json +++ b/package.json @@ -1,77 +1,77 @@ { - "name": "@modrinth/monorepo", - "version": "0.0.0", - "private": true, - "scripts": { - "web:dev": "pnpm i18n:coverage && turbo run dev --filter=@modrinth/frontend", - "web:build": "turbo run build --filter=@modrinth/frontend", - "app:dev": "turbo run dev --filter=@modrinth/app", - "app:build": "turbo run build --filter=@modrinth/app", - "docs:dev": "turbo run dev --filter=@modrinth/docs", - "pages:build": "pnpm i18n:coverage && NITRO_PRESET=cloudflare-pages pnpm --filter frontend run build", - "build": "turbo run build --continue", - "lint": "turbo run lint lint:ancillary --continue", - "lint:ancillary": "prettier --check .github *.*", - "test": "turbo run test --continue", - "fix": "turbo run fix fix:ancillary --continue", - "fix:ancillary": "prettier --write .github *.*", - "ci": "turbo run lint test --continue", - "prepr": "turbo run prepr --continue", - "prepr:frontend": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/app-frontend", - "prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config", - "prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend", - "prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend", - "storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui storybook", - "build-storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui build-storybook", - "icons:add": "pnpm --filter @modrinth/assets icons:add", - "i18n:coverage": "node scripts/run.mjs coverage-i18n --write packages/ui/src/layouts/wrapped/settings/language-settings/language-settings-coverage.generated.ts --quiet", - "changelog:collect": "node scripts/run.mjs collect-changelog", - "changelog:combine-for-app": "node scripts/run.mjs build-theseus-release-notes", - "scripts": "node scripts/run.mjs" - }, - "devDependencies": { - "@clack/prompts": "^1.0.0", - "@crowdin/crowdin-api-client": "^1.55.2", - "@formatjs/icu-messageformat-parser": "^2.11.4", - "@modrinth/tooling-config": "workspace:*", - "@tailwindcss/container-queries": "^0.1.1", - "@types/node": "^24", - "@typescript-eslint/typescript-estree": "^8.64.0", - "@vue/compiler-dom": "^3.5.26", - "@vue/compiler-sfc": "^3.5.26", - "chalk": "^5.6.2", - "if-ci": "^3.0.0", - "keep-a-changelog": "^3.0.2", - "prettier": "^3.3.2", - "turbo": "^2.5.4", - "vue": "^3.5.13", - "yaml": "^2.8.2" - }, - "packageManager": "pnpm@10.33.2", - "engines": { - "node": ">=24.15.0" - }, - "pnpm": { - "patchedDependencies": { - "readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch" - }, - "peerDependencyRules": { - "allowedVersions": { - "vite": "8", - "esbuild": "0" - } - }, - "onlyBuiltDependencies": [ - "@parcel/watcher", - "@sentry/cli", - "core-js", - "esbuild", - "protobufjs", - "sharp", - "unrs-resolver", - "vue-demi", - "workerd" - ] - }, - "prettier": "@modrinth/tooling-config/prettier.config.cjs" + "name": "@modrinth/monorepo", + "version": "0.0.0", + "private": true, + "scripts": { + "web:dev": "pnpm i18n:coverage && turbo run dev --filter=@modrinth/frontend", + "web:build": "turbo run build --filter=@modrinth/frontend", + "app:dev": "turbo run dev --filter=@modrinth/app", + "app:build": "turbo run build --filter=@modrinth/app", + "docs:dev": "turbo run dev --filter=@modrinth/docs", + "pages:build": "pnpm i18n:coverage && NITRO_PRESET=cloudflare-pages pnpm --filter frontend run build", + "build": "turbo run build --continue", + "lint": "turbo run lint lint:ancillary --continue", + "lint:ancillary": "prettier --check .github *.*", + "test": "turbo run test --continue", + "fix": "turbo run fix fix:ancillary --continue", + "fix:ancillary": "prettier --write .github *.*", + "ci": "turbo run lint test --continue", + "prepr": "turbo run prepr --continue", + "prepr:frontend": "turbo run prepr --filter=@modrinth/frontend --filter=@modrinth/app-frontend", + "prepr:frontend:lib": "turbo run prepr --filter=@modrinth/ui --filter=@modrinth/moderation --filter=@modrinth/assets --filter=@modrinth/blog --filter=@modrinth/api-client --filter=@modrinth/utils --filter=@modrinth/tooling-config", + "prepr:frontend:web": "turbo run prepr --filter=@modrinth/frontend", + "prepr:frontend:app": "turbo run prepr --filter=@modrinth/app-frontend", + "storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui storybook", + "build-storybook": "pnpm i18n:coverage && pnpm --filter @modrinth/ui build-storybook", + "icons:add": "pnpm --filter @modrinth/assets icons:add", + "i18n:coverage": "node scripts/run.mjs coverage-i18n --write packages/ui/src/layouts/wrapped/settings/language-settings/language-settings-coverage.generated.ts --quiet", + "changelog:collect": "node scripts/run.mjs collect-changelog", + "changelog:combine-for-app": "node scripts/run.mjs build-theseus-release-notes", + "scripts": "node scripts/run.mjs" + }, + "devDependencies": { + "@clack/prompts": "^1.0.0", + "@crowdin/crowdin-api-client": "^1.55.2", + "@formatjs/icu-messageformat-parser": "^2.11.4", + "@modrinth/tooling-config": "workspace:*", + "@tailwindcss/container-queries": "^0.1.1", + "@types/node": "^24", + "@typescript-eslint/typescript-estree": "^8.64.0", + "@vue/compiler-dom": "^3.5.26", + "@vue/compiler-sfc": "^3.5.26", + "chalk": "^5.6.2", + "if-ci": "^3.0.0", + "keep-a-changelog": "^3.0.2", + "prettier": "^3.3.2", + "turbo": "^2.5.4", + "vue": "^3.5.13", + "yaml": "^2.8.2" + }, + "packageManager": "pnpm@10.33.2", + "engines": { + "node": ">=24.15.0" + }, + "pnpm": { + "patchedDependencies": { + "readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch" + }, + "peerDependencyRules": { + "allowedVersions": { + "vite": "8", + "esbuild": "0" + } + }, + "onlyBuiltDependencies": [ + "@parcel/watcher", + "@sentry/cli", + "core-js", + "esbuild", + "protobufjs", + "sharp", + "unrs-resolver", + "vue-demi", + "workerd" + ] + }, + "prettier": "@modrinth/tooling-config/prettier.config.cjs" } diff --git a/packages/app-lib/Cargo.toml b/packages/app-lib/Cargo.toml index a3a06a0e15..cb585325ca 100644 --- a/packages/app-lib/Cargo.toml +++ b/packages/app-lib/Cargo.toml @@ -12,12 +12,12 @@ async-trait = { workspace = true } async-tungstenite = { workspace = true, features = ["tokio-runtime", "tokio-rustls-webpki-roots"] } async-walkdir = { workspace = true } async_zip = { workspace = true, features = [ - "bzip2", - "chrono", - "deflate", - "deflate64", - "tokio-fs", - "zstd", + "bzip2", + "chrono", + "deflate", + "deflate64", + "tokio-fs", + "zstd", ] } base64 = { workspace = true } bon = { workspace = true } @@ -64,16 +64,16 @@ quick-xml = { workspace = true, features = ["async-tokio"] } rand = { workspace = true } regex = { workspace = true } reqwest = { workspace = true, features = [ - "brotli", - "charset", - "deflate", - "gzip", - "http2", - "json", - "macos-system-configuration", - "multipart", - "rustls-tls-webpki-roots", - "stream", + "brotli", + "charset", + "deflate", + "gzip", + "http2", + "json", + "macos-system-configuration", + "multipart", + "rustls-tls-webpki-roots", + "stream", ] } rgb = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } @@ -85,32 +85,36 @@ sha1_smol = { workspace = true } sha2 = { workspace = true } shlex = { workspace = true } sqlx = { workspace = true, features = [ - "json", - "macros", - "migrate", - "runtime-tokio", - "sqlite", - "uuid", + "json", + "macros", + "migrate", + "runtime-tokio", + "sqlite", + "uuid", ] } sysinfo = { workspace = true, features = ["disk", "system"] } tauri = { workspace = true, features = ["unstable"], optional = true } tempfile = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = [ - "fs", - "io-util", - "macros", - "net", - "process", - "sync", - "time", + "fs", + "io-util", + "macros", + "net", + "process", + "sync", + "time", ] } tokio-util = { workspace = true, features = ["compat", "io", "io-util", "time"] } toml = { workspace = true } tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["chrono", "env-filter"] } -ts-rs = { workspace = true, features = ["chrono-impl", "no-serde-warnings", "uuid-impl"], optional = true } +ts-rs = { workspace = true, features = [ + "chrono-impl", + "no-serde-warnings", + "uuid-impl", +], optional = true } url = { workspace = true, features = ["serde"] } urlencoding = { workspace = true } uuid = { workspace = true, features = ["serde", "v4"] } diff --git a/packages/ui/src/composables/index.ts b/packages/ui/src/composables/index.ts index 3ae88a0335..d48668616c 100644 --- a/packages/ui/src/composables/index.ts +++ b/packages/ui/src/composables/index.ts @@ -14,8 +14,8 @@ export * from './page-leave-safety' export * from './scroll-indicator' export * from './server-backups-queue' export * from './server-console' -export * from './server-download' export * from './server-context-runtime' +export * from './server-download' export * from './server-manage-core-runtime' export * from './server-panel-sync' export * from './server-permissions' diff --git a/turbo.jsonc b/turbo.jsonc index fae1c8dca6..f7ab6d9c34 100644 --- a/turbo.jsonc +++ b/turbo.jsonc @@ -48,12 +48,7 @@ "BUILD_ENV", "PREVIEW" ], - "passThroughEnv": [ - "SCCACHE_*", - "RUSTC_WRAPPER", - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY" - ] + "passThroughEnv": ["SCCACHE_*", "RUSTC_WRAPPER", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] }, "lint": { "env": [ @@ -65,12 +60,7 @@ "FORCE_COLOR", "NEXTEST_*" ], - "passThroughEnv": [ - "SCCACHE_*", - "RUSTC_WRAPPER", - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY" - ] + "passThroughEnv": ["SCCACHE_*", "RUSTC_WRAPPER", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] }, "lint:ancillary": {}, "//#i18n:coverage": { @@ -110,12 +100,7 @@ "FORCE_COLOR", "NEXTEST_*" ], - "passThroughEnv": [ - "SCCACHE_*", - "RUSTC_WRAPPER", - "AWS_ACCESS_KEY_ID", - "AWS_SECRET_ACCESS_KEY" - ] + "passThroughEnv": ["SCCACHE_*", "RUSTC_WRAPPER", "AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY"] }, "fix": {}, "fix:ancillary": { From b592ac15ceb7a4a5f0ad33ec83718193354fb417 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-X=2E=20T=2E?= Date: Fri, 4 Sep 2026 17:22:34 -0400 Subject: [PATCH 4/6] tombi --- Cargo.toml | 146 +++++++++++++++++-------------- _typos.toml | 24 ++--- apps/app/Cargo.toml | 12 +-- apps/daedalus_client/Cargo.toml | 18 ++-- apps/labrinth/Cargo.toml | 81 ++++++++++------- packages/app-lib/Cargo.toml | 69 ++++++++------- packages/sqlx-tracing/Cargo.toml | 7 +- packages/xredis/Cargo.toml | 7 +- 8 files changed, 205 insertions(+), 159 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 168f5d6c35..65fd144b1b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,22 @@ [workspace] resolver = "2" members = [ - "apps/app", - "apps/app-playground", - "apps/daedalus_client", - "apps/labrinth", - "packages/app-lib", - "packages/ariadne", - "packages/component-derive", - "packages/daedalus", - "packages/modrinth-content-management", - "packages/modrinth-log", - "packages/modrinth-maxmind", - "packages/modrinth-util", - "packages/neverbounce", - "packages/path-util", - "packages/serde-binhum", - "packages/xredis", + "apps/app", + "apps/app-playground", + "apps/daedalus_client", + "apps/labrinth", + "packages/app-lib", + "packages/ariadne", + "packages/component-derive", + "packages/daedalus", + "packages/modrinth-content-management", + "packages/modrinth-log", + "packages/modrinth-maxmind", + "packages/modrinth-util", + "packages/neverbounce", + "packages/path-util", + "packages/serde-binhum", + "packages/xredis", ] [workspace.package] @@ -39,28 +39,35 @@ ariadne = { path = "packages/ariadne" } async-minecraft-ping = { path = "packages/async-minecraft-ping" } 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.89" -async-tungstenite = { version = "0.31.0", default-features = false, features = ["futures-03-sink"] } +async-tungstenite = { version = "0.31.0", default-features = false, features = [ + "futures-03-sink" +] } async-walkdir = "2.1.0" async_zip = "0.0.18" aws-sdk-s3 = { version = "=1.122.0", default-features = false, features = [ - "default-https-client", - "rt-tokio", - "rustls", + "default-https-client", + "rt-tokio", + "rustls", ] } base64 = "0.22.1" bitflags = "2.9.4" bon = "3.9.3" bytemuck = "1.24.0" bytes = "1.10.1" -cel = { version = "0.14.0", default-features = false, features = ["json", "regex"] } +cel = { version = "0.14.0", default-features = false, features = [ + "json", + "regex" +] } censor = "0.3.0" chardetng = "0.1.17" chrono = "0.4.42" chumsky = "0.9.3" -cidre = { version = "0.15.0", default-features = false, features = ["macos_15_0"] } +cidre = { version = "0.15.0", default-features = false, features = [ + "macos_15_0" +] } clap = "4.5.48" clickhouse = "0.14.0" color-eyre = "0.6.5" @@ -98,10 +105,10 @@ hmac = "0.12.1" httpdate = "1.0.3" hyper = "1.7.0" hyper-rustls = { version = "0.27.7", default-features = false, features = [ - "aws-lc-rs", - "http1", - "native-tokio", - "tls12", + "aws-lc-rs", + "http1", + "native-tokio", + "tls12", ] } hyper-util = "0.1.17" iana-time-zone = "0.1.64" @@ -113,21 +120,21 @@ jemalloc_pprof = "0.8.1" json-patch = { version = "4.1.0", default-features = false } json5 = "1.3.1" lettre = { version = "0.11.19", default-features = false, features = [ - "aws-lc-rs", - "builder", - "hostname", - "pool", - "rustls", - "rustls-native-certs", - "smtp-transport", - "tokio1", - "tokio1-rustls", + "aws-lc-rs", + "builder", + "hostname", + "pool", + "rustls", + "rustls-native-certs", + "smtp-transport", + "tokio1", + "tokio1-rustls", ] } lz4_flex = { version = "0.11.5", default-features = false, features = [ - "checked-decode", - "safe-decode", - "safe-encode", - "std", + "checked-decode", + "safe-decode", + "safe-encode", + "std", ] } maxminddb = "0.26.0" modrinth-content-management = { path = "packages/modrinth-content-management" } @@ -153,31 +160,34 @@ prometheus = "0.14.0" quartz_nbt = "0.2.9" quick-xml = "0.38.3" quote = { version = "1.0" } -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 rdkafka = { version = "0.36.2", features = ["cmake-build"] } redis = "1.4.1" regex = "1.12.2" reqwest = { version = "0.12.24", default-features = false } rgb = "0.8.52" -rust_decimal = { version = "1.39.0", features = ["serde-with-float", "serde-with-str"] } +rust_decimal = { version = "1.39.0", features = [ + "serde-with-float", + "serde-with-str" +] } rust_iso3166 = "0.1.14" rust-s3 = { version = "0.37.0", default-features = false, features = [ - "fail-on-err", - "tags", - "tokio-rustls-tls", + "fail-on-err", + "tags", + "tokio-rustls-tls", ] } rustls = "0.23.32" rusty-money = "0.4.1" scalar_api_reference = { version = "0.2.2", default-features = false } secrecy = "0.10.3" sentry = { version = "0.45.0", default-features = false, features = [ - "backtrace", - "contexts", - "debug-images", - "panic", - "reqwest", - "rustls", + "backtrace", + "contexts", + "debug-images", + "panic", + "reqwest", + "rustls", ] } serde = "1.0.228" serde-binhum = { path = "packages/serde-binhum" } @@ -208,8 +218,8 @@ tauri-plugin-opener = "2.5.0" tauri-plugin-os = "2.3.1" tauri-plugin-single-instance = "2.3.4" tauri-plugin-updater = { git = "https://github.com/modrinth/plugins-workspace", rev = "0d30f2aa28ec668ce187d527da1c475da3c01cbc", default-features = false, features = [ - "rustls-tls", - "zip", + "rustls-tls", + "zip", ] } tauri-plugin-window-state = "2.4.0" tempfile = "3.23.0" @@ -237,20 +247,20 @@ validator = "0.20.0" webauthn-rs = "0.5.5" webauthn-rs-proto = "0.5.5" webp = { version = "0.3.1", default-features = false } -webview2-com = "0.38.0" # Should be updated in lockstep with wry +webview2-com = "0.38.0" # Should be updated in lockstep with wry whoami = "1.6.1" -windows = "=0.61.3" # Locked on 0.61 until we can update windows-core to 0.62 -windows-core = "=0.61.2" # Locked on 0.61 until webview2-com updates to 0.62 +windows = "=0.61.3" # Locked on 0.61 until we can update windows-core to 0.62 +windows-core = "=0.61.2" # Locked on 0.61 until webview2-com updates to 0.62 winreg = "0.55.0" woothee = "0.13.0" xredis = { path = "packages/xredis" } yaserde = "0.12.0" zbus = "5.11.0" zip = { version = "6.0.0", default-features = false, features = [ - "bzip2", - "deflate", - "deflate64", - "zstd", + "bzip2", + "deflate", + "deflate64", + "zstd", ] } zxcvbn = "3.1.0" @@ -297,15 +307,15 @@ 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 +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 # Specific profile for labrinth production builds [profile.release-labrinth] inherits = "release" opt-level = 2 -strip = false # Keep debug symbols for Sentry -lto = "thin" # Enable LTO but keep compile times reasonable -panic = "unwind" # Don't exit the whole app on panic in production +strip = false # Keep debug symbols for Sentry +lto = "thin" # Enable LTO but keep compile times reasonable +panic = "unwind" # Don't exit the whole app on panic in production diff --git a/_typos.toml b/_typos.toml index 58e28588bc..944064d355 100644 --- a/_typos.toml +++ b/_typos.toml @@ -1,21 +1,21 @@ [files] extend-exclude = [ - "**/src/locales/", - "apps/frontend/", - "patches/", - "packages/utils/", - "packages/ui/", - "packages/blog/", + "**/src/locales/", + "apps/frontend/", + "patches/", + "packages/utils/", + "packages/ui/", + "packages/blog/", ] [default] extend-ignore-re = [ - # Ignore lines that end with `// typos:ignore` - "(?Rm)^.*(#|//)\\s*typos:ignore$", - # Ignore the line after `// typos:ignore`: - "(#|//)\\s*typos:ignore\\n.*", - # Ignore blocks between `// typos:off` and `// typos:on` - "(?s)(#|//)\\s*typos:off.*?\\n\\s*(#|//)\\s*typos:on", + # Ignore lines that end with `// typos:ignore` + "(?Rm)^.*(#|//)\\s*typos:ignore$", + # Ignore the line after `// typos:ignore`: + "(#|//)\\s*typos:ignore\\n.*", + # Ignore blocks between `// typos:off` and `// typos:on` + "(?s)(#|//)\\s*typos:off.*?\\n\\s*(#|//)\\s*typos:on", ] [default.extend-words] diff --git a/apps/app/Cargo.toml b/apps/app/Cargo.toml index a41284eb6c..5e7115cad3 100644 --- a/apps/app/Cargo.toml +++ b/apps/app/Cargo.toml @@ -61,12 +61,12 @@ windows-core.workspace = true [target."cfg(windows)".dependencies.windows] workspace = true features = [ - "Win32_Foundation", - "Win32_Graphics_Dwm", - "Win32_Graphics_Gdi", - "Win32_System_Com", - "Win32_UI_Shell", - "Win32_UI_WindowsAndMessaging", + "Win32_Foundation", + "Win32_Graphics_Dwm", + "Win32_Graphics_Gdi", + "Win32_System_Com", + "Win32_UI_Shell", + "Win32_UI_WindowsAndMessaging", ] [features] diff --git a/apps/daedalus_client/Cargo.toml b/apps/daedalus_client/Cargo.toml index b6b40664fb..4f12976e04 100644 --- a/apps/daedalus_client/Cargo.toml +++ b/apps/daedalus_client/Cargo.toml @@ -5,12 +5,12 @@ edition.workspace = true [dependencies] async_zip = { workspace = true, features = [ - "bzip2", - "chrono", - "deflate", - "deflate64", - "tokio-fs", - "zstd", + "bzip2", + "chrono", + "deflate", + "deflate64", + "tokio-fs", + "zstd", ] } bytes = { workspace = true } chrono = { workspace = true, features = ["serde"] } @@ -21,7 +21,11 @@ futures = { workspace = true } indexmap = { workspace = true, features = ["serde"] } itertools = { workspace = true } quick-xml = { workspace = true } -reqwest = { workspace = true, features = ["json", "rustls-tls-native-roots", "stream"] } +reqwest = { workspace = true, features = [ + "json", + "rustls-tls-native-roots", + "stream" +] } rust-s3 = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/apps/labrinth/Cargo.toml b/apps/labrinth/Cargo.toml index e76823ee69..b0f0a05059 100644 --- a/apps/labrinth/Cargo.toml +++ b/apps/labrinth/Cargo.toml @@ -22,7 +22,12 @@ arc-swap = { workspace = true } argon2 = { workspace = true } ariadne = { workspace = true } async-minecraft-ping = { workspace = true, features = ["srv"] } -async-stripe = { workspace = true, features = ["billing", "checkout", "connect", "webhook-events"] } +async-stripe = { workspace = true, features = [ + "billing", + "checkout", + "connect", + "webhook-events" +] } async-trait = { workspace = true } aws-sdk-s3 = { workspace = true } base64 = { workspace = true } @@ -51,21 +56,21 @@ hmac = { workspace = true } hyper-rustls = { workspace = true } hyper-util = { workspace = true } image = { workspace = true, features = [ - "avif", - "bmp", - "dds", - "exr", - "ff", - "gif", - "hdr", - "ico", - "jpeg", - "png", - "pnm", - "qoi", - "tga", - "tiff", - "webp", + "avif", + "bmp", + "dds", + "exr", + "ff", + "gif", + "hdr", + "ico", + "jpeg", + "png", + "pnm", + "qoi", + "tga", + "tiff", + "webp", ] } itertools = { workspace = true } json-patch = { workspace = true } @@ -83,10 +88,24 @@ quick-xml = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } rdkafka = { workspace = true } -redis = { workspace = true, features = ["ahash", "cluster", "cluster-async", "r2d2", "tokio-comp"] } +redis = { workspace = true, features = [ + "ahash", + "cluster", + "cluster-async", + "r2d2", + "tokio-comp" +] } regex = { workspace = true } -reqwest = { workspace = true, features = ["http2", "json", "multipart", "rustls-tls-webpki-roots"] } -rust_decimal = { workspace = true, features = ["serde-with-float", "serde-with-str"] } +reqwest = { workspace = true, features = [ + "http2", + "json", + "multipart", + "rustls-tls-webpki-roots" +] } +rust_decimal = { workspace = true, features = [ + "serde-with-float", + "serde-with-str" +] } rust_iso3166 = { workspace = true } rustls.workspace = true rusty-money = { workspace = true } @@ -101,14 +120,14 @@ sha2 = { workspace = true } smallvec = { workspace = true } spdx = { workspace = true, features = ["text"] } sqlx = { workspace = true, features = [ - "chrono", - "json", - "macros", - "migrate", - "postgres", - "runtime-tokio", - "rust_decimal", - "tls-rustls-aws-lc-rs", + "chrono", + "json", + "macros", + "migrate", + "postgres", + "runtime-tokio", + "rust_decimal", + "tls-rustls-aws-lc-rs", ] } sqlx-tracing = { workspace = true, features = ["postgres"] } strum = { workspace = true, features = ["derive"] } @@ -124,8 +143,8 @@ utoipa = { workspace = true, features = ["url"] } uuid = { workspace = true, features = ["fast-rng", "serde", "v4", "v7"] } validator = { workspace = true, features = ["derive"] } webauthn-rs = { workspace = true, features = [ - "conditional-ui", - "danger-allow-state-serialisation", + "conditional-ui", + "danger-allow-state-serialisation", ] } webauthn-rs-proto = { workspace = true } webp = { workspace = true } @@ -148,8 +167,8 @@ iana-time-zone = { workspace = true } jemalloc_pprof = { workspace = true, features = ["flamegraph"] } tikv-jemalloc-ctl = { workspace = true, features = ["stats"] } tikv-jemallocator = { workspace = true, features = [ - "profiling", - "unprefixed_malloc_on_supported_platforms", + "profiling", + "unprefixed_malloc_on_supported_platforms", ] } [features] diff --git a/packages/app-lib/Cargo.toml b/packages/app-lib/Cargo.toml index cb585325ca..6d50aa6a90 100644 --- a/packages/app-lib/Cargo.toml +++ b/packages/app-lib/Cargo.toml @@ -9,15 +9,18 @@ ariadne = { workspace = true } async-minecraft-ping = { workspace = true, features = ["srv"] } async-recursion = { workspace = true } async-trait = { workspace = true } -async-tungstenite = { workspace = true, features = ["tokio-runtime", "tokio-rustls-webpki-roots"] } +async-tungstenite = { workspace = true, features = [ + "tokio-runtime", + "tokio-rustls-webpki-roots" +] } async-walkdir = { workspace = true } async_zip = { workspace = true, features = [ - "bzip2", - "chrono", - "deflate", - "deflate64", - "tokio-fs", - "zstd", + "bzip2", + "chrono", + "deflate", + "deflate64", + "tokio-fs", + "zstd", ] } base64 = { workspace = true } bon = { workspace = true } @@ -64,16 +67,16 @@ quick-xml = { workspace = true, features = ["async-tokio"] } rand = { workspace = true } regex = { workspace = true } reqwest = { workspace = true, features = [ - "brotli", - "charset", - "deflate", - "gzip", - "http2", - "json", - "macos-system-configuration", - "multipart", - "rustls-tls-webpki-roots", - "stream", + "brotli", + "charset", + "deflate", + "gzip", + "http2", + "json", + "macos-system-configuration", + "multipart", + "rustls-tls-webpki-roots", + "stream", ] } rgb = { workspace = true } serde = { workspace = true, features = ["derive", "rc"] } @@ -85,25 +88,25 @@ sha1_smol = { workspace = true } sha2 = { workspace = true } shlex = { workspace = true } sqlx = { workspace = true, features = [ - "json", - "macros", - "migrate", - "runtime-tokio", - "sqlite", - "uuid", + "json", + "macros", + "migrate", + "runtime-tokio", + "sqlite", + "uuid", ] } sysinfo = { workspace = true, features = ["disk", "system"] } tauri = { workspace = true, features = ["unstable"], optional = true } tempfile = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true, features = [ - "fs", - "io-util", - "macros", - "net", - "process", - "sync", - "time", + "fs", + "io-util", + "macros", + "net", + "process", + "sync", + "time", ] } tokio-util = { workspace = true, features = ["compat", "io", "io-util", "time"] } toml = { workspace = true } @@ -111,9 +114,9 @@ tracing = { workspace = true } tracing-error = { workspace = true } tracing-subscriber = { workspace = true, features = ["chrono", "env-filter"] } ts-rs = { workspace = true, features = [ - "chrono-impl", - "no-serde-warnings", - "uuid-impl", + "chrono-impl", + "no-serde-warnings", + "uuid-impl", ], optional = true } url = { workspace = true, features = ["serde"] } urlencoding = { workspace = true } diff --git a/packages/sqlx-tracing/Cargo.toml b/packages/sqlx-tracing/Cargo.toml index 3ce51c659a..bf89e32aa8 100644 --- a/packages/sqlx-tracing/Cargo.toml +++ b/packages/sqlx-tracing/Cargo.toml @@ -10,7 +10,12 @@ repository = "https://github.com/jdrouet/sqlx-tracing" license = "MIT" # authors = ["Jérémie Drouet "] # deprecated field, Tombi warns keywords = ["database", "observability", "opentelemetry", "sqlx", "tracing"] -categories = ["asynchronous", "database", "development-tools::debugging", "development-tools::profiling"] +categories = [ + "asynchronous", + "database", + "development-tools::debugging", + "development-tools::profiling" +] [dependencies] derive_more = { workspace = true, features = ["deref", "deref_mut"] } diff --git a/packages/xredis/Cargo.toml b/packages/xredis/Cargo.toml index 14a698c047..cc87779098 100644 --- a/packages/xredis/Cargo.toml +++ b/packages/xredis/Cargo.toml @@ -15,7 +15,12 @@ futures = { workspace = true } lz4_flex = { workspace = true } postcard = { workspace = true } prometheus = { workspace = true } -redis = { workspace = true, features = ["ahash", "cluster", "cluster-async", "tokio-comp"] } +redis = { workspace = true, features = [ + "ahash", + "cluster", + "cluster-async", + "tokio-comp" +] } serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["rt", "sync", "time"] } From 2bb4c640766905e26dc49cc41a176292f84df68a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-X=2E=20T=2E?= Date: Fri, 4 Sep 2026 17:26:49 -0400 Subject: [PATCH 5/6] gg --- Cargo.toml | 18 ++++-------------- apps/daedalus_client/Cargo.toml | 6 +----- apps/labrinth/Cargo.toml | 27 ++++----------------------- packages/app-lib/Cargo.toml | 5 +---- packages/sqlx-tracing/Cargo.toml | 7 +------ packages/xredis/Cargo.toml | 7 +------ 6 files changed, 12 insertions(+), 58 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 65fd144b1b..99b0c562a5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,9 +42,7 @@ async-stripe = { version = "0.41.0", default-features = false, features = [ "runtime-tokio-hyper-rustls", ] } async-trait = "0.1.89" -async-tungstenite = { version = "0.31.0", default-features = false, features = [ - "futures-03-sink" -] } +async-tungstenite = { version = "0.31.0", default-features = false, features = ["futures-03-sink"] } async-walkdir = "2.1.0" async_zip = "0.0.18" aws-sdk-s3 = { version = "=1.122.0", default-features = false, features = [ @@ -57,17 +55,12 @@ bitflags = "2.9.4" bon = "3.9.3" bytemuck = "1.24.0" bytes = "1.10.1" -cel = { version = "0.14.0", default-features = false, features = [ - "json", - "regex" -] } +cel = { version = "0.14.0", default-features = false, features = ["json", "regex"] } censor = "0.3.0" chardetng = "0.1.17" chrono = "0.4.42" chumsky = "0.9.3" -cidre = { version = "0.15.0", default-features = false, features = [ - "macos_15_0" -] } +cidre = { version = "0.15.0", default-features = false, features = ["macos_15_0"] } clap = "4.5.48" clickhouse = "0.14.0" color-eyre = "0.6.5" @@ -167,10 +160,7 @@ redis = "1.4.1" regex = "1.12.2" reqwest = { version = "0.12.24", default-features = false } rgb = "0.8.52" -rust_decimal = { version = "1.39.0", features = [ - "serde-with-float", - "serde-with-str" -] } +rust_decimal = { version = "1.39.0", features = ["serde-with-float", "serde-with-str"] } rust_iso3166 = "0.1.14" rust-s3 = { version = "0.37.0", default-features = false, features = [ "fail-on-err", diff --git a/apps/daedalus_client/Cargo.toml b/apps/daedalus_client/Cargo.toml index 4f12976e04..7296a32249 100644 --- a/apps/daedalus_client/Cargo.toml +++ b/apps/daedalus_client/Cargo.toml @@ -21,11 +21,7 @@ futures = { workspace = true } indexmap = { workspace = true, features = ["serde"] } itertools = { workspace = true } quick-xml = { workspace = true } -reqwest = { workspace = true, features = [ - "json", - "rustls-tls-native-roots", - "stream" -] } +reqwest = { workspace = true, features = ["json", "rustls-tls-native-roots", "stream"] } rust-s3 = { workspace = true } serde = { workspace = true, features = ["derive"] } serde_json = { workspace = true } diff --git a/apps/labrinth/Cargo.toml b/apps/labrinth/Cargo.toml index b0f0a05059..6445a6a60d 100644 --- a/apps/labrinth/Cargo.toml +++ b/apps/labrinth/Cargo.toml @@ -22,12 +22,7 @@ arc-swap = { workspace = true } argon2 = { workspace = true } ariadne = { workspace = true } async-minecraft-ping = { workspace = true, features = ["srv"] } -async-stripe = { workspace = true, features = [ - "billing", - "checkout", - "connect", - "webhook-events" -] } +async-stripe = { workspace = true, features = ["billing", "checkout", "connect", "webhook-events"] } async-trait = { workspace = true } aws-sdk-s3 = { workspace = true } base64 = { workspace = true } @@ -88,24 +83,10 @@ quick-xml = { workspace = true } rand = { workspace = true } rand_chacha = { workspace = true } rdkafka = { workspace = true } -redis = { workspace = true, features = [ - "ahash", - "cluster", - "cluster-async", - "r2d2", - "tokio-comp" -] } +redis = { workspace = true, features = ["ahash", "cluster", "cluster-async", "r2d2", "tokio-comp"] } regex = { workspace = true } -reqwest = { workspace = true, features = [ - "http2", - "json", - "multipart", - "rustls-tls-webpki-roots" -] } -rust_decimal = { workspace = true, features = [ - "serde-with-float", - "serde-with-str" -] } +reqwest = { workspace = true, features = ["http2", "json", "multipart", "rustls-tls-webpki-roots"] } +rust_decimal = { workspace = true, features = ["serde-with-float", "serde-with-str"] } rust_iso3166 = { workspace = true } rustls.workspace = true rusty-money = { workspace = true } diff --git a/packages/app-lib/Cargo.toml b/packages/app-lib/Cargo.toml index 6d50aa6a90..69545c27b3 100644 --- a/packages/app-lib/Cargo.toml +++ b/packages/app-lib/Cargo.toml @@ -9,10 +9,7 @@ ariadne = { workspace = true } async-minecraft-ping = { workspace = true, features = ["srv"] } async-recursion = { workspace = true } async-trait = { workspace = true } -async-tungstenite = { workspace = true, features = [ - "tokio-runtime", - "tokio-rustls-webpki-roots" -] } +async-tungstenite = { workspace = true, features = ["tokio-runtime", "tokio-rustls-webpki-roots"] } async-walkdir = { workspace = true } async_zip = { workspace = true, features = [ "bzip2", diff --git a/packages/sqlx-tracing/Cargo.toml b/packages/sqlx-tracing/Cargo.toml index bf89e32aa8..3ce51c659a 100644 --- a/packages/sqlx-tracing/Cargo.toml +++ b/packages/sqlx-tracing/Cargo.toml @@ -10,12 +10,7 @@ repository = "https://github.com/jdrouet/sqlx-tracing" license = "MIT" # authors = ["Jérémie Drouet "] # deprecated field, Tombi warns keywords = ["database", "observability", "opentelemetry", "sqlx", "tracing"] -categories = [ - "asynchronous", - "database", - "development-tools::debugging", - "development-tools::profiling" -] +categories = ["asynchronous", "database", "development-tools::debugging", "development-tools::profiling"] [dependencies] derive_more = { workspace = true, features = ["deref", "deref_mut"] } diff --git a/packages/xredis/Cargo.toml b/packages/xredis/Cargo.toml index cc87779098..14a698c047 100644 --- a/packages/xredis/Cargo.toml +++ b/packages/xredis/Cargo.toml @@ -15,12 +15,7 @@ futures = { workspace = true } lz4_flex = { workspace = true } postcard = { workspace = true } prometheus = { workspace = true } -redis = { workspace = true, features = [ - "ahash", - "cluster", - "cluster-async", - "tokio-comp" -] } +redis = { workspace = true, features = ["ahash", "cluster", "cluster-async", "tokio-comp"] } serde = { workspace = true, features = ["derive"] } thiserror = { workspace = true } tokio = { workspace = true, features = ["rt", "sync", "time"] } From 052ef565f5e9345b8069f931a989144259ff95df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-X=2E=20T=2E?= Date: Fri, 4 Sep 2026 18:12:43 -0400 Subject: [PATCH 6/6] intl --- packages/ui/src/locales/en-US/index.json | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json index 6b205816b9..5207c916bf 100644 --- a/packages/ui/src/locales/en-US/index.json +++ b/packages/ui/src/locales/en-US/index.json @@ -206,6 +206,9 @@ "button.download": { "defaultMessage": "Download" }, + "button.download-files": { + "defaultMessage": "Download files" + }, "button.downloading": { "defaultMessage": "Downloading" }, @@ -5162,6 +5165,18 @@ "servers.busy.installing": { "defaultMessage": "Server is installing" }, + "servers.download.failed.description": { + "defaultMessage": "An error occurred while trying to download the world's files." + }, + "servers.download.failed.title": { + "defaultMessage": "Download failed" + }, + "servers.download.unavailable.description": { + "defaultMessage": "This world's files cannot currently be downloaded." + }, + "servers.download.unavailable.title": { + "defaultMessage": "Download unavailable" + }, "servers.files.zip-created": { "defaultMessage": "ZIP created" }, @@ -5315,9 +5330,6 @@ "servers.listing.copy-id-label": { "defaultMessage": "Copy ID" }, - "servers.listing.download-world-tooltip": { - "defaultMessage": "Download world files" - }, "servers.listing.manage-billing-label": { "defaultMessage": "Manage billing" },