From c7d0839bfb7681462f38e96d58396025c4bb0630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Gonz=C3=A1lez?= <7822554+AlexTMjugador@users.noreply.github.com> Date: Tue, 29 Jul 2025 11:51:50 +0200 Subject: [PATCH 1/8] fix(labrinth): retire Sendy for new email newsletter subscriptions (#4073) * tweak(frontend): do not sign up for the newsletter by default * fix(labrinth): retire Sendy for new email newsletter subscriptions --- apps/frontend/src/pages/auth/sign-up.vue | 2 +- ...d46bc09344c1846b3098accce5801e571e5e.json} | 5 +- ...29b0535241bbb6d74143925e16cf8cd720c4.json} | 10 ++- ...7e34bf813ddbfb88bf31b9863078bc48c8623.json | 14 +++ ...20_user-newsletter-subscription-column.sql | 1 + apps/labrinth/src/auth/validate.rs | 33 +++++-- .../labrinth/src/database/models/user_item.rs | 10 ++- apps/labrinth/src/routes/internal/flows.rs | 90 ++++++++----------- 8 files changed, 95 insertions(+), 70 deletions(-) rename apps/labrinth/.sqlx/{query-32fa1030a3a69f6bc36c6ec916ba8d0724dfd683576629ab05f5df321d5f9a55.json => query-010c69fa61e1329156020b251e75d46bc09344c1846b3098accce5801e571e5e.json} (71%) rename apps/labrinth/.sqlx/{query-b5857aafa522ca62294bc296fb6cddd862eca2889203e43b4962df07ba1221a0.json => query-5fcdeeeb820ada62e10feb0beefa29b0535241bbb6d74143925e16cf8cd720c4.json} (88%) create mode 100644 apps/labrinth/.sqlx/query-c960b09ddc19530383f143c349c7e34bf813ddbfb88bf31b9863078bc48c8623.json create mode 100644 apps/labrinth/migrations/20250727184120_user-newsletter-subscription-column.sql diff --git a/apps/frontend/src/pages/auth/sign-up.vue b/apps/frontend/src/pages/auth/sign-up.vue index 7f88fa512..a8cb5664c 100644 --- a/apps/frontend/src/pages/auth/sign-up.vue +++ b/apps/frontend/src/pages/auth/sign-up.vue @@ -218,7 +218,7 @@ const username = ref(""); const password = ref(""); const confirmPassword = ref(""); const token = ref(""); -const subscribe = ref(true); +const subscribe = ref(false); async function createAccount() { startLoading(); diff --git a/apps/labrinth/.sqlx/query-32fa1030a3a69f6bc36c6ec916ba8d0724dfd683576629ab05f5df321d5f9a55.json b/apps/labrinth/.sqlx/query-010c69fa61e1329156020b251e75d46bc09344c1846b3098accce5801e571e5e.json similarity index 71% rename from apps/labrinth/.sqlx/query-32fa1030a3a69f6bc36c6ec916ba8d0724dfd683576629ab05f5df321d5f9a55.json rename to apps/labrinth/.sqlx/query-010c69fa61e1329156020b251e75d46bc09344c1846b3098accce5801e571e5e.json index 8d844ddf9..082a6e4e2 100644 --- a/apps/labrinth/.sqlx/query-32fa1030a3a69f6bc36c6ec916ba8d0724dfd683576629ab05f5df321d5f9a55.json +++ b/apps/labrinth/.sqlx/query-010c69fa61e1329156020b251e75d46bc09344c1846b3098accce5801e571e5e.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n INSERT INTO users (\n id, username, email,\n avatar_url, raw_avatar_url, bio, created,\n github_id, discord_id, gitlab_id, google_id, steam_id, microsoft_id,\n email_verified, password, paypal_id, paypal_country, paypal_email,\n venmo_handle, stripe_customer_id, allow_friend_requests\n )\n VALUES (\n $1, $2, $3, $4, $5,\n $6, $7,\n $8, $9, $10, $11, $12, $13,\n $14, $15, $16, $17, $18, $19, $20, $21\n )\n ", + "query": "\n INSERT INTO users (\n id, username, email,\n avatar_url, raw_avatar_url, bio, created,\n github_id, discord_id, gitlab_id, google_id, steam_id, microsoft_id,\n email_verified, password, paypal_id, paypal_country, paypal_email,\n venmo_handle, stripe_customer_id, allow_friend_requests, is_subscribed_to_newsletter\n )\n VALUES (\n $1, $2, $3, $4, $5,\n $6, $7,\n $8, $9, $10, $11, $12, $13,\n $14, $15, $16, $17, $18, $19, $20, $21, $22\n )\n ", "describe": { "columns": [], "parameters": { @@ -25,10 +25,11 @@ "Text", "Text", "Text", + "Bool", "Bool" ] }, "nullable": [] }, - "hash": "32fa1030a3a69f6bc36c6ec916ba8d0724dfd683576629ab05f5df321d5f9a55" + "hash": "010c69fa61e1329156020b251e75d46bc09344c1846b3098accce5801e571e5e" } diff --git a/apps/labrinth/.sqlx/query-b5857aafa522ca62294bc296fb6cddd862eca2889203e43b4962df07ba1221a0.json b/apps/labrinth/.sqlx/query-5fcdeeeb820ada62e10feb0beefa29b0535241bbb6d74143925e16cf8cd720c4.json similarity index 88% rename from apps/labrinth/.sqlx/query-b5857aafa522ca62294bc296fb6cddd862eca2889203e43b4962df07ba1221a0.json rename to apps/labrinth/.sqlx/query-5fcdeeeb820ada62e10feb0beefa29b0535241bbb6d74143925e16cf8cd720c4.json index 988ec11ad..0c33202b9 100644 --- a/apps/labrinth/.sqlx/query-b5857aafa522ca62294bc296fb6cddd862eca2889203e43b4962df07ba1221a0.json +++ b/apps/labrinth/.sqlx/query-5fcdeeeb820ada62e10feb0beefa29b0535241bbb6d74143925e16cf8cd720c4.json @@ -1,6 +1,6 @@ { "db_name": "PostgreSQL", - "query": "\n SELECT id, email,\n avatar_url, raw_avatar_url, username, bio,\n created, role, badges,\n github_id, discord_id, gitlab_id, google_id, steam_id, microsoft_id,\n email_verified, password, totp_secret, paypal_id, paypal_country, paypal_email,\n venmo_handle, stripe_customer_id, allow_friend_requests\n FROM users\n WHERE id = ANY($1) OR LOWER(username) = ANY($2)\n ", + "query": "\n SELECT id, email,\n avatar_url, raw_avatar_url, username, bio,\n created, role, badges,\n github_id, discord_id, gitlab_id, google_id, steam_id, microsoft_id,\n email_verified, password, totp_secret, paypal_id, paypal_country, paypal_email,\n venmo_handle, stripe_customer_id, allow_friend_requests, is_subscribed_to_newsletter\n FROM users\n WHERE id = ANY($1) OR LOWER(username) = ANY($2)\n ", "describe": { "columns": [ { @@ -122,6 +122,11 @@ "ordinal": 23, "name": "allow_friend_requests", "type_info": "Bool" + }, + { + "ordinal": 24, + "name": "is_subscribed_to_newsletter", + "type_info": "Bool" } ], "parameters": { @@ -154,8 +159,9 @@ true, true, true, + false, false ] }, - "hash": "b5857aafa522ca62294bc296fb6cddd862eca2889203e43b4962df07ba1221a0" + "hash": "5fcdeeeb820ada62e10feb0beefa29b0535241bbb6d74143925e16cf8cd720c4" } diff --git a/apps/labrinth/.sqlx/query-c960b09ddc19530383f143c349c7e34bf813ddbfb88bf31b9863078bc48c8623.json b/apps/labrinth/.sqlx/query-c960b09ddc19530383f143c349c7e34bf813ddbfb88bf31b9863078bc48c8623.json new file mode 100644 index 000000000..975dc151a --- /dev/null +++ b/apps/labrinth/.sqlx/query-c960b09ddc19530383f143c349c7e34bf813ddbfb88bf31b9863078bc48c8623.json @@ -0,0 +1,14 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE users\n SET is_subscribed_to_newsletter = TRUE\n WHERE id = $1\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8" + ] + }, + "nullable": [] + }, + "hash": "c960b09ddc19530383f143c349c7e34bf813ddbfb88bf31b9863078bc48c8623" +} diff --git a/apps/labrinth/migrations/20250727184120_user-newsletter-subscription-column.sql b/apps/labrinth/migrations/20250727184120_user-newsletter-subscription-column.sql new file mode 100644 index 000000000..5a475b68b --- /dev/null +++ b/apps/labrinth/migrations/20250727184120_user-newsletter-subscription-column.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN is_subscribed_to_newsletter BOOLEAN NOT NULL DEFAULT FALSE; diff --git a/apps/labrinth/src/auth/validate.rs b/apps/labrinth/src/auth/validate.rs index 806eaa126..325adc3d5 100644 --- a/apps/labrinth/src/auth/validate.rs +++ b/apps/labrinth/src/auth/validate.rs @@ -1,6 +1,6 @@ use super::AuthProvider; use crate::auth::AuthenticationError; -use crate::database::models::user_item; +use crate::database::models::{DBUser, user_item}; use crate::database::redis::RedisPool; use crate::models::pats::Scopes; use crate::models::users::User; @@ -44,17 +44,16 @@ where Ok(Some((scopes, User::from_full(db_user)))) } -pub async fn get_user_from_headers<'a, E>( +pub async fn get_full_user_from_headers<'a, E>( req: &HttpRequest, executor: E, redis: &RedisPool, session_queue: &AuthQueue, required_scopes: Scopes, -) -> Result<(Scopes, User), AuthenticationError> +) -> Result<(Scopes, DBUser), AuthenticationError> where E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, { - // Fetch DB user record and minos user from headers let (scopes, db_user) = get_user_record_from_bearer_token( req, None, @@ -65,13 +64,33 @@ where .await? .ok_or_else(|| AuthenticationError::InvalidCredentials)?; - let user = User::from_full(db_user); - if !scopes.contains(required_scopes) { return Err(AuthenticationError::InvalidCredentials); } - Ok((scopes, user)) + Ok((scopes, db_user)) +} + +pub async fn get_user_from_headers<'a, E>( + req: &HttpRequest, + executor: E, + redis: &RedisPool, + session_queue: &AuthQueue, + required_scopes: Scopes, +) -> Result<(Scopes, User), AuthenticationError> +where + E: sqlx::Executor<'a, Database = sqlx::Postgres> + Copy, +{ + let (scopes, db_user) = get_full_user_from_headers( + req, + executor, + redis, + session_queue, + required_scopes, + ) + .await?; + + Ok((scopes, User::from_full(db_user))) } pub async fn get_user_record_from_bearer_token<'a, 'b, E>( diff --git a/apps/labrinth/src/database/models/user_item.rs b/apps/labrinth/src/database/models/user_item.rs index 6a2e4aba6..4d447702d 100644 --- a/apps/labrinth/src/database/models/user_item.rs +++ b/apps/labrinth/src/database/models/user_item.rs @@ -49,6 +49,8 @@ pub struct DBUser { pub badges: Badges, pub allow_friend_requests: bool, + + pub is_subscribed_to_newsletter: bool, } impl DBUser { @@ -63,13 +65,13 @@ impl DBUser { avatar_url, raw_avatar_url, bio, created, github_id, discord_id, gitlab_id, google_id, steam_id, microsoft_id, email_verified, password, paypal_id, paypal_country, paypal_email, - venmo_handle, stripe_customer_id, allow_friend_requests + venmo_handle, stripe_customer_id, allow_friend_requests, is_subscribed_to_newsletter ) VALUES ( $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, - $14, $15, $16, $17, $18, $19, $20, $21 + $14, $15, $16, $17, $18, $19, $20, $21, $22 ) ", self.id as DBUserId, @@ -93,6 +95,7 @@ impl DBUser { self.venmo_handle, self.stripe_customer_id, self.allow_friend_requests, + self.is_subscribed_to_newsletter, ) .execute(&mut **transaction) .await?; @@ -178,7 +181,7 @@ impl DBUser { created, role, badges, github_id, discord_id, gitlab_id, google_id, steam_id, microsoft_id, email_verified, password, totp_secret, paypal_id, paypal_country, paypal_email, - venmo_handle, stripe_customer_id, allow_friend_requests + venmo_handle, stripe_customer_id, allow_friend_requests, is_subscribed_to_newsletter FROM users WHERE id = ANY($1) OR LOWER(username) = ANY($2) ", @@ -212,6 +215,7 @@ impl DBUser { stripe_customer_id: u.stripe_customer_id, totp_secret: u.totp_secret, allow_friend_requests: u.allow_friend_requests, + is_subscribed_to_newsletter: u.is_subscribed_to_newsletter, }; acc.insert(u.id, (Some(u.username), user)); diff --git a/apps/labrinth/src/routes/internal/flows.rs b/apps/labrinth/src/routes/internal/flows.rs index 281f85be0..cba2de5d9 100644 --- a/apps/labrinth/src/routes/internal/flows.rs +++ b/apps/labrinth/src/routes/internal/flows.rs @@ -1,5 +1,7 @@ use crate::auth::email::send_email; -use crate::auth::validate::get_user_record_from_bearer_token; +use crate::auth::validate::{ + get_full_user_from_headers, get_user_record_from_bearer_token, +}; use crate::auth::{AuthProvider, AuthenticationError, get_user_from_headers}; use crate::database::models::DBUser; use crate::database::models::flow_item::DBFlow; @@ -232,6 +234,7 @@ impl TempUser { role: Role::Developer.to_string(), badges: Badges::default(), allow_friend_requests: true, + is_subscribed_to_newsletter: false, } .insert(transaction) .await?; @@ -1291,37 +1294,6 @@ pub async fn delete_auth_provider( Ok(HttpResponse::NoContent().finish()) } -pub async fn sign_up_sendy(email: &str) -> Result<(), AuthenticationError> { - let url = dotenvy::var("SENDY_URL")?; - let id = dotenvy::var("SENDY_LIST_ID")?; - let api_key = dotenvy::var("SENDY_API_KEY")?; - let site_url = dotenvy::var("SITE_URL")?; - - if url.is_empty() || url == "none" { - tracing::info!("Sendy URL not set, skipping signup"); - return Ok(()); - } - - let mut form = HashMap::new(); - - form.insert("api_key", &*api_key); - form.insert("email", email); - form.insert("list", &*id); - form.insert("referrer", &*site_url); - - let client = reqwest::Client::new(); - client - .post(format!("{url}/subscribe")) - .form(&form) - .send() - .await? - .error_for_status()? - .text() - .await?; - - Ok(()) -} - pub async fn check_sendy_subscription( email: &str, ) -> Result { @@ -1456,6 +1428,9 @@ pub async fn create_account_with_password( role: Role::Developer.to_string(), badges: Badges::default(), allow_friend_requests: true, + is_subscribed_to_newsletter: new_account + .sign_up_newsletter + .unwrap_or(false), } .insert(&mut transaction) .await?; @@ -1476,10 +1451,6 @@ pub async fn create_account_with_password( &format!("Welcome to Modrinth, {}!", new_account.username), )?; - if new_account.sign_up_newsletter.unwrap_or(false) { - sign_up_sendy(&new_account.email).await?; - } - transaction.commit().await?; Ok(HttpResponse::Ok().json(res)) @@ -2420,15 +2391,24 @@ pub async fn subscribe_newsletter( .await? .1; - if let Some(email) = user.email { - sign_up_sendy(&email).await?; + sqlx::query!( + " + UPDATE users + SET is_subscribed_to_newsletter = TRUE + WHERE id = $1 + ", + user.id.0 as i64, + ) + .execute(&**pool) + .await?; - Ok(HttpResponse::NoContent().finish()) - } else { - Err(ApiError::InvalidInput( - "User does not have an email.".to_string(), - )) - } + crate::database::models::DBUser::clear_caches( + &[(user.id.into(), None)], + &redis, + ) + .await?; + + Ok(HttpResponse::NoContent().finish()) } #[get("email/subscribe")] @@ -2438,7 +2418,7 @@ pub async fn get_newsletter_subscription_status( redis: Data, session_queue: Data, ) -> Result { - let user = get_user_from_headers( + let user = get_full_user_from_headers( &req, &**pool, &redis, @@ -2448,16 +2428,16 @@ pub async fn get_newsletter_subscription_status( .await? .1; - if let Some(email) = user.email { - let is_subscribed = check_sendy_subscription(&email).await?; - Ok(HttpResponse::Ok().json(serde_json::json!({ - "subscribed": is_subscribed - }))) - } else { - Ok(HttpResponse::Ok().json(serde_json::json!({ - "subscribed": false - }))) - } + let is_subscribed = user.is_subscribed_to_newsletter + || if let Some(email) = user.email { + check_sendy_subscription(&email).await? + } else { + false + }; + + Ok(HttpResponse::Ok().json(serde_json::json!({ + "subscribed": is_subscribed + }))) } fn send_email_verify( From 6387fb21c6948190b2ed2cbda0568eff379179ab Mon Sep 17 00:00:00 2001 From: IMB11 Date: Tue, 29 Jul 2025 22:19:25 +0100 Subject: [PATCH 2/8] feat: Moderation Dashboard Overhaul (#4059) * feat: Moderation Dashboard Overhaul * fix: lint issues * fix: issues * fix: report layout * fix: lint * fix: impl quick replies * fix: remove test qr * feat: individual report page + use new backend * feat: memoize filtering * feat: apply optimizations to moderation queue * fix: lint issues * feat: impl quick reply functionality * fix: top level await * fix: dep issue * fix: dep issue x2 * fix: dep issue * feat: intl extract * fix: dev-187 * fix: dev-186 & review project btn * fix: dev-176 * remove redundant moderation button from user dropdown * correct a msg and add admin to read filter --------- Co-authored-by: coolbot100s <76798835+coolbot100s@users.noreply.github.com> --- apps/frontend/package.json | 2 + .../src/components/ui/ModerationChecklist.vue | 1133 ----------------- .../moderation/ModerationDelphiReportCard.vue | 179 +++ .../ui/moderation/ModerationQueueCard.vue | 204 +++ .../ui/moderation/ModerationReportCard.vue | 275 ++++ .../ChecklistKeybindsModal.vue | 4 +- .../ModerationChecklist.vue} | 182 +-- .../ModpackPermissionsFlow.vue | 0 .../src/components/ui/thread/ReportThread.vue | 282 ++++ .../components/ui/thread/ThreadMessage.vue | 2 +- apps/frontend/src/helpers/moderation.ts | 236 ++++ apps/frontend/src/layouts/default.vue | 19 +- apps/frontend/src/locales/en-US/index.json | 24 + apps/frontend/src/pages/[type]/[id].vue | 31 +- .../src/pages/[type]/[id]/gallery.vue | 2 + apps/frontend/src/pages/moderation.vue | 97 +- apps/frontend/src/pages/moderation/index.vue | 365 +++++- .../src/pages/moderation/report/[id].vue | 17 - .../frontend/src/pages/moderation/reports.vue | 16 - .../src/pages/moderation/reports/[id].vue | 28 + .../src/pages/moderation/reports/index.vue | 290 +++++ apps/frontend/src/pages/moderation/review.vue | 304 ----- .../moderation/technical-review-mockup.vue | 386 ++++++ .../src/pages/moderation/technical-review.vue | 3 + apps/frontend/src/store/moderation.ts | 98 ++ packages/assets/generated-icons.ts | 4 + packages/assets/icons/collapse.svg | 8 + packages/assets/icons/ellipsis-vertical.svg | 1 + .../data/messages/reports/antivirus.md | 3 + .../messages/reports/confirmed-malware.md | 3 + .../data/messages/reports/gameplay-issue.md | 6 + .../data/messages/reports/platform-issue.md | 5 + .../moderation/data/messages/reports/spam.md | 3 + .../moderation/data/messages/reports/stale.md | 3 + .../moderation/data/report-quick-replies.ts | 34 + packages/moderation/data/stages/versions.ts | 2 +- packages/moderation/index.ts | 4 +- packages/moderation/types/reports.ts | 28 + .../src/components/base/CollapsibleRegion.vue | 97 ++ .../ui/src/components/base/DropdownSelect.vue | 1 - packages/ui/src/components/index.ts | 1 + packages/utils/types.ts | 95 +- pnpm-lock.yaml | 540 ++++---- 43 files changed, 3114 insertions(+), 1903 deletions(-) delete mode 100644 apps/frontend/src/components/ui/ModerationChecklist.vue create mode 100644 apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue create mode 100644 apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue create mode 100644 apps/frontend/src/components/ui/moderation/ModerationReportCard.vue rename apps/frontend/src/components/ui/moderation/{ => checklist}/ChecklistKeybindsModal.vue (96%) rename apps/frontend/src/components/ui/moderation/{NewModerationChecklist.vue => checklist/ModerationChecklist.vue} (90%) rename apps/frontend/src/components/ui/moderation/{ => checklist}/ModpackPermissionsFlow.vue (100%) create mode 100644 apps/frontend/src/components/ui/thread/ReportThread.vue create mode 100644 apps/frontend/src/helpers/moderation.ts delete mode 100644 apps/frontend/src/pages/moderation/report/[id].vue delete mode 100644 apps/frontend/src/pages/moderation/reports.vue create mode 100644 apps/frontend/src/pages/moderation/reports/[id].vue create mode 100644 apps/frontend/src/pages/moderation/reports/index.vue delete mode 100644 apps/frontend/src/pages/moderation/review.vue create mode 100644 apps/frontend/src/pages/moderation/technical-review-mockup.vue create mode 100644 apps/frontend/src/pages/moderation/technical-review.vue create mode 100644 apps/frontend/src/store/moderation.ts create mode 100644 packages/assets/icons/collapse.svg create mode 100644 packages/assets/icons/ellipsis-vertical.svg create mode 100644 packages/moderation/data/messages/reports/antivirus.md create mode 100644 packages/moderation/data/messages/reports/confirmed-malware.md create mode 100644 packages/moderation/data/messages/reports/gameplay-issue.md create mode 100644 packages/moderation/data/messages/reports/platform-issue.md create mode 100644 packages/moderation/data/messages/reports/spam.md create mode 100644 packages/moderation/data/messages/reports/stale.md create mode 100644 packages/moderation/data/report-quick-replies.ts create mode 100644 packages/moderation/types/reports.ts create mode 100644 packages/ui/src/components/base/CollapsibleRegion.vue diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 7cded8314..011eafb64 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -59,10 +59,12 @@ "markdown-it": "14.1.0", "pathe": "^1.1.2", "pinia": "^2.1.7", + "pinia-plugin-persistedstate": "^4.4.1", "prettier": "^3.6.2", "qrcode.vue": "^3.4.0", "semver": "^7.5.4", "three": "^0.172.0", + "vue-confetti-explosion": "^1.0.2", "vue-multiselect": "3.0.0-alpha.2", "vue-typed-virtual-list": "^1.0.10", "vue3-ace-editor": "^2.2.4", diff --git a/apps/frontend/src/components/ui/ModerationChecklist.vue b/apps/frontend/src/components/ui/ModerationChecklist.vue deleted file mode 100644 index b21fd9954..000000000 --- a/apps/frontend/src/components/ui/ModerationChecklist.vue +++ /dev/null @@ -1,1133 +0,0 @@ - - - - - diff --git a/apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue b/apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue new file mode 100644 index 000000000..961f340a3 --- /dev/null +++ b/apps/frontend/src/components/ui/moderation/ModerationDelphiReportCard.vue @@ -0,0 +1,179 @@ + + + + + diff --git a/apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue b/apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue new file mode 100644 index 000000000..385a2033b --- /dev/null +++ b/apps/frontend/src/components/ui/moderation/ModerationQueueCard.vue @@ -0,0 +1,204 @@ + + + diff --git a/apps/frontend/src/components/ui/moderation/ModerationReportCard.vue b/apps/frontend/src/components/ui/moderation/ModerationReportCard.vue new file mode 100644 index 000000000..499b1d381 --- /dev/null +++ b/apps/frontend/src/components/ui/moderation/ModerationReportCard.vue @@ -0,0 +1,275 @@ + + + + diff --git a/apps/frontend/src/components/ui/moderation/ChecklistKeybindsModal.vue b/apps/frontend/src/components/ui/moderation/checklist/ChecklistKeybindsModal.vue similarity index 96% rename from apps/frontend/src/components/ui/moderation/ChecklistKeybindsModal.vue rename to apps/frontend/src/components/ui/moderation/checklist/ChecklistKeybindsModal.vue index 787474bc5..db8b931ba 100644 --- a/apps/frontend/src/components/ui/moderation/ChecklistKeybindsModal.vue +++ b/apps/frontend/src/components/ui/moderation/checklist/ChecklistKeybindsModal.vue @@ -29,7 +29,7 @@ diff --git a/apps/frontend/src/components/ui/thread/ThreadMessage.vue b/apps/frontend/src/components/ui/thread/ThreadMessage.vue index 9d962c98e..f47b06613 100644 --- a/apps/frontend/src/components/ui/thread/ThreadMessage.vue +++ b/apps/frontend/src/components/ui/thread/ThreadMessage.vue @@ -36,7 +36,7 @@ v-tooltip="'Modrinth Team'" /> diff --git a/apps/frontend/src/helpers/moderation.ts b/apps/frontend/src/helpers/moderation.ts new file mode 100644 index 000000000..0e842fef8 --- /dev/null +++ b/apps/frontend/src/helpers/moderation.ts @@ -0,0 +1,236 @@ +import type { ExtendedReport, OwnershipTarget } from "@modrinth/moderation"; +import type { + Thread, + Version, + User, + Project, + TeamMember, + Organization, + Report, +} from "@modrinth/utils"; + +export const useModerationCache = () => ({ + threads: useState>("moderation-report-cache-threads", () => new Map()), + users: useState>("moderation-report-cache-users", () => new Map()), + projects: useState>("moderation-report-cache-projects", () => new Map()), + versions: useState>("moderation-report-cache-versions", () => new Map()), + teams: useState>("moderation-report-cache-teams", () => new Map()), + orgs: useState>("moderation-report-cache-orgs", () => new Map()), +}); + +// TODO: @AlexTMjugador - backend should do all of these functions. +export async function enrichReportBatch(reports: Report[]): Promise { + if (reports.length === 0) return []; + + const cache = useModerationCache(); + + const threadIDs = reports + .map((r) => r.thread_id) + .filter(Boolean) + .filter((id) => !cache.threads.value.has(id)); + const userIDs = [ + ...reports.filter((r) => r.item_type === "user").map((r) => r.item_id), + ...reports.map((r) => r.reporter), + ].filter((id) => !cache.users.value.has(id)); + const versionIDs = reports + .filter((r) => r.item_type === "version") + .map((r) => r.item_id) + .filter((id) => !cache.versions.value.has(id)); + const projectIDs = reports + .filter((r) => r.item_type === "project") + .map((r) => r.item_id) + .filter((id) => !cache.projects.value.has(id)); + + const [newThreads, newVersions, newUsers] = await Promise.all([ + threadIDs.length > 0 + ? (fetchSegmented(threadIDs, (ids) => `threads?ids=${asEncodedJsonArray(ids)}`) as Promise< + Thread[] + >) + : Promise.resolve([]), + versionIDs.length > 0 + ? (fetchSegmented(versionIDs, (ids) => `versions?ids=${asEncodedJsonArray(ids)}`) as Promise< + Version[] + >) + : Promise.resolve([]), + [...new Set(userIDs)].length > 0 + ? (fetchSegmented( + [...new Set(userIDs)], + (ids) => `users?ids=${asEncodedJsonArray(ids)}`, + ) as Promise) + : Promise.resolve([]), + ]); + + newThreads.forEach((t) => cache.threads.value.set(t.id, t)); + newVersions.forEach((v) => cache.versions.value.set(v.id, v)); + newUsers.forEach((u) => cache.users.value.set(u.id, u)); + + const allVersions = [...newVersions, ...Array.from(cache.versions.value.values())]; + const fullProjectIds = new Set([ + ...projectIDs, + ...allVersions + .filter((v) => versionIDs.includes(v.id)) + .map((v) => v.project_id) + .filter(Boolean), + ]); + + const uncachedProjectIds = Array.from(fullProjectIds).filter( + (id) => !cache.projects.value.has(id), + ); + const newProjects = + uncachedProjectIds.length > 0 + ? ((await fetchSegmented( + uncachedProjectIds, + (ids) => `projects?ids=${asEncodedJsonArray(ids)}`, + )) as Project[]) + : []; + + newProjects.forEach((p) => cache.projects.value.set(p.id, p)); + + const allProjects = [...newProjects, ...Array.from(cache.projects.value.values())]; + const teamIds = [...new Set(allProjects.map((p) => p.team).filter(Boolean))].filter( + (id) => !cache.teams.value.has(id || "invalid team id"), + ); + const orgIds = [...new Set(allProjects.map((p) => p.organization).filter(Boolean))].filter( + (id) => !cache.orgs.value.has(id), + ); + + const [newTeams, newOrgs] = await Promise.all([ + teamIds.length > 0 + ? (fetchSegmented(teamIds, (ids) => `teams?ids=${asEncodedJsonArray(ids)}`) as Promise< + TeamMember[][] + >) + : Promise.resolve([]), + orgIds.length > 0 + ? (fetchSegmented(orgIds, (ids) => `organizations?ids=${asEncodedJsonArray(ids)}`, { + apiVersion: 3, + }) as Promise) + : Promise.resolve([]), + ]); + + newTeams.forEach((team) => { + if (team.length > 0) cache.teams.value.set(team[0].team_id, team); + }); + newOrgs.forEach((org) => cache.orgs.value.set(org.id, org)); + + return reports.map((report) => { + const thread = cache.threads.value.get(report.thread_id) || ({} as Thread); + const version = + report.item_type === "version" ? cache.versions.value.get(report.item_id) : undefined; + + const project = + report.item_type === "project" + ? cache.projects.value.get(report.item_id) + : report.item_type === "version" && version + ? cache.projects.value.get(version.project_id) + : undefined; + + let target: OwnershipTarget | undefined; + + if (report.item_type === "user") { + const targetUser = cache.users.value.get(report.item_id); + if (targetUser) { + target = { + name: targetUser.username, + slug: targetUser.username, + avatar_url: targetUser.avatar_url, + type: "user", + }; + } + } else if (project) { + let owner: TeamMember | null = null; + let org: Organization | null = null; + + if (project.team) { + const teamMembers = cache.teams.value.get(project.team); + if (teamMembers) { + owner = teamMembers.find((member) => member.role === "Owner") || null; + } + } + + if (project.organization) { + org = cache.orgs.value.get(project.organization) || null; + } + + if (org) { + target = { + name: org.name, + avatar_url: org.icon_url, + type: "organization", + slug: org.slug, + }; + } else if (owner) { + target = { + name: owner.user.username, + avatar_url: owner.user.avatar_url, + type: "user", + slug: owner.user.username, + }; + } + } + + return { + ...report, + thread, + reporter_user: cache.users.value.get(report.reporter) || ({} as User), + project, + user: report.item_type === "user" ? cache.users.value.get(report.item_id) : undefined, + version, + target, + }; + }); +} + +// Doesn't need to be in @modrinth/moderation because it is specific to the frontend. +export interface ModerationProject { + project: any; + owner: TeamMember | null; + org: Organization | null; +} + +export async function enrichProjectBatch(projects: any[]): Promise { + const teamIds = [...new Set(projects.map((p) => p.team_id).filter(Boolean))]; + const orgIds = [...new Set(projects.map((p) => p.organization).filter(Boolean))]; + + const [teamsData, orgsData]: [TeamMember[][], Organization[]] = await Promise.all([ + teamIds.length > 0 + ? fetchSegmented(teamIds, (ids) => `teams?ids=${asEncodedJsonArray(ids)}`) + : Promise.resolve([]), + orgIds.length > 0 + ? fetchSegmented(orgIds, (ids) => `organizations?ids=${asEncodedJsonArray(ids)}`, { + apiVersion: 3, + }) + : Promise.resolve([]), + ]); + + const cache = useModerationCache(); + + teamsData.forEach((team) => { + if (team.length > 0) cache.teams.value.set(team[0].team_id, team); + }); + + orgsData.forEach((org: Organization) => { + cache.orgs.value.set(org.id, org); + }); + + return projects.map((project) => { + let owner: TeamMember | null = null; + let org: Organization | null = null; + + if (project.team_id) { + const teamMembers = cache.teams.value.get(project.team_id); + if (teamMembers) { + owner = teamMembers.find((member) => member.role === "Owner") || null; + } + } + + if (project.organization) { + org = cache.orgs.value.get(project.organization) || null; + } + + return { + project, + owner, + org, + } as ModerationProject; + }); +} diff --git a/apps/frontend/src/layouts/default.vue b/apps/frontend/src/layouts/default.vue index 308b7e3a9..0a118099c 100644 --- a/apps/frontend/src/layouts/default.vue +++ b/apps/frontend/src/layouts/default.vue @@ -295,7 +295,7 @@ { id: 'review-projects', color: 'orange', - link: '/moderation/review', + link: '/moderation/', }, { id: 'review-reports', @@ -981,23 +981,6 @@ const userMenuOptions = computed(() => { }, ]; - if ( - (auth.value && auth.value.user && auth.value.user.role === "moderator") || - auth.value.user.role === "admin" - ) { - options = [ - ...options, - { - divider: true, - }, - { - id: "moderation", - color: "orange", - link: "/moderation/review", - }, - ]; - } - options = [ ...options, { diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index 38e72448e..3a5bdd371 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -476,6 +476,30 @@ "layout.nav.search": { "message": "Search" }, + "moderation.filter.by": { + "message": "Filter by" + }, + "moderation.moderate": { + "message": "Moderate" + }, + "moderation.page.projects": { + "message": "Projects" + }, + "moderation.page.reports": { + "message": "Reports" + }, + "moderation.page.technicalReview": { + "message": "Technical Review" + }, + "moderation.search.placeholder": { + "message": "Search..." + }, + "moderation.sort.by": { + "message": "Sort by" + }, + "moderation.technical.search.placeholder": { + "message": "Search tech reviews..." + }, "profile.button.billing": { "message": "Manage user billing" }, diff --git a/apps/frontend/src/pages/[type]/[id].vue b/apps/frontend/src/pages/[type]/[id].vue index 2bb35162f..1dc0cfd6b 100644 --- a/apps/frontend/src/pages/[type]/[id].vue +++ b/apps/frontend/src/pages/[type]/[id].vue @@ -689,7 +689,10 @@ }, { id: 'moderation-checklist', - action: () => (showModerationChecklist = true), + action: () => { + moderationStore.setSingleProject(project.id); + showModerationChecklist = true; + }, color: 'orange', hoverOnly: true, shown: @@ -870,19 +873,6 @@ @delete-version="deleteVersion" /> - -
- - -
@@ -890,9 +880,8 @@ v-if="auth.user && tags.staffRoles.includes(auth.user.role) && showModerationChecklist" class="moderation-checklist" > - { - console.log("Future project IDs updated:", newValue); -}); - watch( showModerationChecklist, (newValue) => { diff --git a/apps/frontend/src/pages/[type]/[id]/gallery.vue b/apps/frontend/src/pages/[type]/[id]/gallery.vue index 35eb72a2c..7b5327ed3 100644 --- a/apps/frontend/src/pages/[type]/[id]/gallery.vue +++ b/apps/frontend/src/pages/[type]/[id]/gallery.vue @@ -365,8 +365,10 @@ export default defineNuxtComponent({ if (e.key === "Escape") { this.expandedGalleryItem = null; } else if (e.key === "ArrowLeft") { + e.stopPropagation(); this.previousImage(); } else if (e.key === "ArrowRight") { + e.stopPropagation(); this.nextImage(); } } diff --git a/apps/frontend/src/pages/moderation.vue b/apps/frontend/src/pages/moderation.vue index 4dbb509d6..3de15993c 100644 --- a/apps/frontend/src/pages/moderation.vue +++ b/apps/frontend/src/pages/moderation.vue @@ -1,33 +1,84 @@ - diff --git a/apps/frontend/src/pages/moderation/index.vue b/apps/frontend/src/pages/moderation/index.vue index aa4ff5fa7..c344d7cbf 100644 --- a/apps/frontend/src/pages/moderation/index.vue +++ b/apps/frontend/src/pages/moderation/index.vue @@ -1,42 +1,339 @@ - diff --git a/apps/frontend/src/pages/moderation/report/[id].vue b/apps/frontend/src/pages/moderation/report/[id].vue deleted file mode 100644 index d485333d2..000000000 --- a/apps/frontend/src/pages/moderation/report/[id].vue +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/apps/frontend/src/pages/moderation/reports.vue b/apps/frontend/src/pages/moderation/reports.vue deleted file mode 100644 index af15186e1..000000000 --- a/apps/frontend/src/pages/moderation/reports.vue +++ /dev/null @@ -1,16 +0,0 @@ - - diff --git a/apps/frontend/src/pages/moderation/reports/[id].vue b/apps/frontend/src/pages/moderation/reports/[id].vue new file mode 100644 index 000000000..8ec2c4d67 --- /dev/null +++ b/apps/frontend/src/pages/moderation/reports/[id].vue @@ -0,0 +1,28 @@ + + + diff --git a/apps/frontend/src/pages/moderation/reports/index.vue b/apps/frontend/src/pages/moderation/reports/index.vue new file mode 100644 index 000000000..4d375ffeb --- /dev/null +++ b/apps/frontend/src/pages/moderation/reports/index.vue @@ -0,0 +1,290 @@ + + + diff --git a/apps/frontend/src/pages/moderation/review.vue b/apps/frontend/src/pages/moderation/review.vue deleted file mode 100644 index 0613982d4..000000000 --- a/apps/frontend/src/pages/moderation/review.vue +++ /dev/null @@ -1,304 +0,0 @@ - - - - diff --git a/apps/frontend/src/pages/moderation/technical-review-mockup.vue b/apps/frontend/src/pages/moderation/technical-review-mockup.vue new file mode 100644 index 000000000..f18897fc6 --- /dev/null +++ b/apps/frontend/src/pages/moderation/technical-review-mockup.vue @@ -0,0 +1,386 @@ + + + diff --git a/apps/frontend/src/pages/moderation/technical-review.vue b/apps/frontend/src/pages/moderation/technical-review.vue new file mode 100644 index 000000000..40f28feca --- /dev/null +++ b/apps/frontend/src/pages/moderation/technical-review.vue @@ -0,0 +1,3 @@ + diff --git a/apps/frontend/src/store/moderation.ts b/apps/frontend/src/store/moderation.ts new file mode 100644 index 000000000..d89a68fcd --- /dev/null +++ b/apps/frontend/src/store/moderation.ts @@ -0,0 +1,98 @@ +import { defineStore, createPinia } from "pinia"; +import piniaPluginPersistedstate from "pinia-plugin-persistedstate"; + +export interface ModerationQueue { + items: string[]; + total: number; + completed: number; + skipped: number; + lastUpdated: Date; +} + +const EMPTY_QUEUE: Partial = { + items: [], + + // TODO: Consider some form of displaying this in the checklist, maybe at the end + total: 0, + completed: 0, + skipped: 0, +}; + +function createEmptyQueue(): ModerationQueue { + return { ...EMPTY_QUEUE, lastUpdated: new Date() } as ModerationQueue; +} + +const pinia = createPinia(); +pinia.use(piniaPluginPersistedstate); + +export const useModerationStore = defineStore("moderation", { + state: () => ({ + currentQueue: createEmptyQueue(), + }), + + getters: { + queueLength: (state) => state.currentQueue.items.length, + hasItems: (state) => state.currentQueue.items.length > 0, + progress: (state) => { + if (state.currentQueue.total === 0) return 0; + return (state.currentQueue.completed + state.currentQueue.skipped) / state.currentQueue.total; + }, + }, + + actions: { + setQueue(projectIDs: string[]) { + this.currentQueue = { + items: [...projectIDs], + total: projectIDs.length, + completed: 0, + skipped: 0, + lastUpdated: new Date(), + }; + }, + + setSingleProject(projectId: string) { + this.currentQueue = { + items: [projectId], + total: 1, + completed: 0, + skipped: 0, + lastUpdated: new Date(), + }; + }, + + completeCurrentProject(projectId: string, status: "completed" | "skipped" = "completed") { + if (status === "completed") { + this.currentQueue.completed++; + } else { + this.currentQueue.skipped++; + } + + this.currentQueue.items = this.currentQueue.items.filter((id: string) => id !== projectId); + this.currentQueue.lastUpdated = new Date(); + + return this.currentQueue.items.length > 0; + }, + + getCurrentProjectId(): string | null { + return this.currentQueue.items[0] || null; + }, + + resetQueue() { + this.currentQueue = createEmptyQueue(); + }, + }, + + persist: { + key: "moderation-store", + serializer: { + serialize: JSON.stringify, + deserialize: (value: string) => { + const parsed = JSON.parse(value); + if (parsed.currentQueue?.lastUpdated) { + parsed.currentQueue.lastUpdated = new Date(parsed.currentQueue.lastUpdated); + } + return parsed; + }, + }, + }, +}); diff --git a/packages/assets/generated-icons.ts b/packages/assets/generated-icons.ts index 249a53b60..f01044155 100644 --- a/packages/assets/generated-icons.ts +++ b/packages/assets/generated-icons.ts @@ -38,6 +38,7 @@ import _CodeIcon from './icons/code.svg?component' import _CoffeeIcon from './icons/coffee.svg?component' import _CogIcon from './icons/cog.svg?component' import _CoinsIcon from './icons/coins.svg?component' +import _CollapseIcon from './icons/collapse.svg?component' import _CollectionIcon from './icons/collection.svg?component' import _CompassIcon from './icons/compass.svg?component' import _ContractIcon from './icons/contract.svg?component' @@ -52,6 +53,7 @@ import _DatabaseIcon from './icons/database.svg?component' import _DownloadIcon from './icons/download.svg?component' import _DropdownIcon from './icons/dropdown.svg?component' import _EditIcon from './icons/edit.svg?component' +import _EllipsisVerticalIcon from './icons/ellipsis-vertical.svg?component' import _ExpandIcon from './icons/expand.svg?component' import _ExternalIcon from './icons/external.svg?component' import _EyeOffIcon from './icons/eye-off.svg?component' @@ -229,6 +231,7 @@ export const CodeIcon = _CodeIcon export const CoffeeIcon = _CoffeeIcon export const CogIcon = _CogIcon export const CoinsIcon = _CoinsIcon +export const CollapseIcon = _CollapseIcon export const CollectionIcon = _CollectionIcon export const CompassIcon = _CompassIcon export const ContractIcon = _ContractIcon @@ -243,6 +246,7 @@ export const DatabaseIcon = _DatabaseIcon export const DownloadIcon = _DownloadIcon export const DropdownIcon = _DropdownIcon export const EditIcon = _EditIcon +export const EllipsisVerticalIcon = _EllipsisVerticalIcon export const ExpandIcon = _ExpandIcon export const ExternalIcon = _ExternalIcon export const EyeOffIcon = _EyeOffIcon diff --git a/packages/assets/icons/collapse.svg b/packages/assets/icons/collapse.svg new file mode 100644 index 000000000..49723c697 --- /dev/null +++ b/packages/assets/icons/collapse.svg @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/packages/assets/icons/ellipsis-vertical.svg b/packages/assets/icons/ellipsis-vertical.svg new file mode 100644 index 000000000..ebe30683a --- /dev/null +++ b/packages/assets/icons/ellipsis-vertical.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/moderation/data/messages/reports/antivirus.md b/packages/moderation/data/messages/reports/antivirus.md new file mode 100644 index 000000000..338dd8d6f --- /dev/null +++ b/packages/moderation/data/messages/reports/antivirus.md @@ -0,0 +1,3 @@ +Unfortunately, anti-virus software has consistently been found to be an unreliable tool for Minecraft mods. + +If you have evidence of malicious activity concerning a specific mod, or of malicious code decompiled from a mod on Modrinth, please create a new Report and provide the required details, thank you. diff --git a/packages/moderation/data/messages/reports/confirmed-malware.md b/packages/moderation/data/messages/reports/confirmed-malware.md new file mode 100644 index 000000000..5f7cc2a51 --- /dev/null +++ b/packages/moderation/data/messages/reports/confirmed-malware.md @@ -0,0 +1,3 @@ +Thank you for your report. + +This project was confirmed to be malicious after a detailed investigation. Luckily, thanks to your report and quick action from our team, we have reason to believe this did not impact a significant amount of users and we have taken precautions to prevent this malicious code from appearing on Modrinth again. diff --git a/packages/moderation/data/messages/reports/gameplay-issue.md b/packages/moderation/data/messages/reports/gameplay-issue.md new file mode 100644 index 000000000..ee0c9dd99 --- /dev/null +++ b/packages/moderation/data/messages/reports/gameplay-issue.md @@ -0,0 +1,6 @@ +Unfortunately, the Moderation team is unable to assist with your issue. + +The reporting system is exclusively for reporting issues to Moderation staff; only violations of [Modrinth's Content Rules](https://modrinth.com/legal/rules) should be reported. The members of the project you're reporting do not see that you have submitted a report. + +If you are having issues with crashes, please check out [our FAQ section](https://support.modrinth.com/aen/articles/8792916) to learn how to diagnose and fix crashes. +For other project-specific issues consider asking the project's own community, check for a Discord or Issues link on the project page. diff --git a/packages/moderation/data/messages/reports/platform-issue.md b/packages/moderation/data/messages/reports/platform-issue.md new file mode 100644 index 000000000..a6bcd943d --- /dev/null +++ b/packages/moderation/data/messages/reports/platform-issue.md @@ -0,0 +1,5 @@ +Unfortunately, the Moderation team is unable to assist with your issue. + +The reporting system is exclusively for reporting issues to Moderation staff; only violations of [Modrinth's Content Rules](https://modrinth.com/legal/rules) should be reported. + +Please reach out to the [Modrinth Help Center](https://support.modrinth.com/) so we can better assist you and bring up your concerns with our platform tean, diff --git a/packages/moderation/data/messages/reports/spam.md b/packages/moderation/data/messages/reports/spam.md new file mode 100644 index 000000000..876dda2bd --- /dev/null +++ b/packages/moderation/data/messages/reports/spam.md @@ -0,0 +1,3 @@ +The reporting system is exclusively for reporting issues to Modrinth staff; only violations of [Modrinth's Content Rules](https://modrinth.com/legal/rules) should be reported. The members of the project you're reporting do not see that you have submitted a report. + +Please ensure you are using the Reports system appropriately, repeated misuse may result in account suspension. diff --git a/packages/moderation/data/messages/reports/stale.md b/packages/moderation/data/messages/reports/stale.md new file mode 100644 index 000000000..cc21f5f18 --- /dev/null +++ b/packages/moderation/data/messages/reports/stale.md @@ -0,0 +1,3 @@ +We haven't received a response in some time, so we're closing this report thread. + +If you have additional information to share we ask that you create a new report. diff --git a/packages/moderation/data/report-quick-replies.ts b/packages/moderation/data/report-quick-replies.ts new file mode 100644 index 000000000..db1fd232a --- /dev/null +++ b/packages/moderation/data/report-quick-replies.ts @@ -0,0 +1,34 @@ +import type { ReportQuickReply } from '../types/reports' + +export default [ + { + label: 'Antivirus', + message: async () => (await import('./messages/reports/antivirus.md?raw')).default, + private: false, + }, + { + label: 'Spam', + message: async () => (await import('./messages/reports/spam.md?raw')).default, + private: false, + }, + { + label: 'Gameplay Issue', + message: async () => (await import('./messages/reports/gameplay-issue.md?raw')).default, + private: false, + }, + { + label: 'Platform Issue', + message: async () => (await import('./messages/reports/platform-issue.md?raw')).default, + private: false, + }, + { + label: 'Stale', + message: async () => (await import('./messages/reports/stale.md?raw')).default, + private: false, + }, + { + label: 'Confirmed Malware', + message: async () => (await import('./messages/reports/confirmed-malware.md?raw')).default, + private: false, + }, +] as ReadonlyArray diff --git a/packages/moderation/data/stages/versions.ts b/packages/moderation/data/stages/versions.ts index 9976fa968..7f5ca33a0 100644 --- a/packages/moderation/data/stages/versions.ts +++ b/packages/moderation/data/stages/versions.ts @@ -68,7 +68,7 @@ const versions: Stage = { message: async () => '', enablesActions: [ { - id: 'versions_incorrect_project_type_options', + id: 'versions_alternate_versions_options', type: 'dropdown', label: 'How are the alternate versions distributed?', options: [ diff --git a/packages/moderation/index.ts b/packages/moderation/index.ts index a7cebdcd5..0ee0afdf4 100644 --- a/packages/moderation/index.ts +++ b/packages/moderation/index.ts @@ -2,8 +2,10 @@ export * from './types/actions' export * from './types/messages' export * from './types/stage' export * from './types/keybinds' +export * from './types/reports' export * from './utils' -export { finalPermissionMessages } from './data/modpack-permissions-stage' +export { finalPermissionMessages } from './data/modpack-permissions-stage' export { default as checklist } from './data/checklist' export { default as keybinds } from './data/keybinds' +export { default as reportQuickReplies } from './data/report-quick-replies' diff --git a/packages/moderation/types/reports.ts b/packages/moderation/types/reports.ts new file mode 100644 index 000000000..c05dc348b --- /dev/null +++ b/packages/moderation/types/reports.ts @@ -0,0 +1,28 @@ +import type { Project, Report, Thread, User, Version, DelphiReport } from '@modrinth/utils' + +export interface OwnershipTarget { + name: string + slug: string + avatar_url?: string + type: 'user' | 'organization' +} + +export interface ExtendedReport extends Report { + thread: Thread + reporter_user: User + project?: Project + user?: User + version?: Version + target?: OwnershipTarget +} + +export interface ExtendedDelphiReport extends DelphiReport { + target?: OwnershipTarget +} + +export interface ReportQuickReply { + label: string + message: string | ((report: ExtendedReport) => Promise | string) + shouldShow?: (report: ExtendedReport) => boolean + private?: boolean +} diff --git a/packages/ui/src/components/base/CollapsibleRegion.vue b/packages/ui/src/components/base/CollapsibleRegion.vue new file mode 100644 index 000000000..14d06c839 --- /dev/null +++ b/packages/ui/src/components/base/CollapsibleRegion.vue @@ -0,0 +1,97 @@ + + + + + diff --git a/packages/ui/src/components/base/DropdownSelect.vue b/packages/ui/src/components/base/DropdownSelect.vue index c87ef340b..9843eb152 100644 --- a/packages/ui/src/components/base/DropdownSelect.vue +++ b/packages/ui/src/components/base/DropdownSelect.vue @@ -163,7 +163,6 @@ const onFocus = () => { } const onBlur = (event) => { - console.log(event) if (!isChildOfDropdown(event.relatedTarget)) { dropdownVisible.value = false } diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index e1217fc59..85b7f2da0 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -10,6 +10,7 @@ export { default as Card } from './base/Card.vue' export { default as Checkbox } from './base/Checkbox.vue' export { default as Chips } from './base/Chips.vue' export { default as Collapsible } from './base/Collapsible.vue' +export { default as CollapsibleRegion } from './base/CollapsibleRegion.vue' export { default as ContentPageHeader } from './base/ContentPageHeader.vue' export { default as CopyCode } from './base/CopyCode.vue' export { default as DoubleIcon } from './base/DoubleIcon.vue' diff --git a/packages/utils/types.ts b/packages/utils/types.ts index a56bc3c56..61f553a20 100644 --- a/packages/utils/types.ts +++ b/packages/utils/types.ts @@ -18,7 +18,7 @@ export type DonationPlatform = | { short: 'ko-fi'; name: 'Ko-fi' } | { short: 'other'; name: 'Other' } -export type ProjectType = 'mod' | 'modpack' | 'resourcepack' | 'shader' +export type ProjectType = 'mod' | 'modpack' | 'resourcepack' | 'shader' | 'plugin' | 'datapack' export type MonetizationStatus = 'monetized' | 'demonetized' | 'force-demonetized' export type GameVersion = string @@ -65,7 +65,8 @@ export interface Project { client_side: Environment server_side: Environment - team: ModrinthId + team?: ModrinthId + team_id: ModrinthId thread_id: ModrinthId organization: ModrinthId @@ -76,6 +77,7 @@ export interface Project { donation_urls: DonationLink[] published: string + created?: string updated: string approved: string queued: string @@ -295,6 +297,60 @@ export type Report = { body: string } +// Threads +export interface Thread { + id: string + type: ThreadType + project_id: string | null + report_id: string | null + messages: ThreadMessage[] + members: User[] +} + +export type ThreadType = 'project' | 'report' | 'direct_message' + +export interface ThreadMessage { + id: string | null + author_id: string | null + body: MessageBody + created: string + hide_identity: boolean +} + +export type MessageBody = + | TextMessageBody + | StatusChangeMessageBody + | ThreadClosureMessageBody + | ThreadReopenMessageBody + | DeletedMessageBody + +export interface TextMessageBody { + type: 'text' + body: string + private: boolean + replying_to: string | null + associated_images: string[] +} + +export interface StatusChangeMessageBody { + type: 'status_change' + new_status: ProjectStatus + old_status: ProjectStatus +} + +export interface ThreadClosureMessageBody { + type: 'thread_closure' +} + +export interface ThreadReopenMessageBody { + type: 'thread_reopen' +} + +export interface DeletedMessageBody { + type: 'deleted' + private: boolean +} + // Moderation export interface ModerationModpackPermissionApprovalType { id: @@ -379,3 +435,38 @@ export interface ModerationJudgement { export interface ModerationJudgements { [sha1: string]: ModerationJudgement } + +// Delphi +export interface DelphiReport { + id: string + project: Project + version: Version + priority_score: number + detected_at: string + trace_type: + | 'reflection_indirection' + | 'xor_obfuscation' + | 'included_libraries' + | 'suspicious_binaries' + | 'corrupt_classes' + | 'suspicious_classes' + | 'url_usage' + | 'classloader_usage' + | 'processbuilder_usage' + | 'runtime_exec_usage' + | 'jni_usage' + | 'main_method' + | 'native_loading' + | 'malformed_jar' + | 'nested_jar_too_deep' + | 'failed_decompilation' + | 'analysis_failure' + | 'malware_easyforme' + | 'malware_simplyloader' + file_path: string + // pending = not reviewed yet. + // approved = approved as malicious, removed from modrinth + // rejected = not approved as malicious, remains on modrinth? + status: 'pending' | 'approved' | 'rejected' + content?: string +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index a37c90435..c311ab042 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -125,31 +125,31 @@ importers: devDependencies: '@eslint/compat': specifier: ^1.1.1 - version: 1.2.1(eslint@9.13.0(jiti@2.4.2)) + version: 1.2.1(eslint@9.13.0(jiti@2.5.1)) '@formatjs/cli': specifier: ^6.2.12 version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) '@nuxt/eslint-config': specifier: ^0.5.6 - version: 0.5.7(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + version: 0.5.7(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@taijased/vue-render-tracker': specifier: ^1.0.7 version: 1.0.7(vue@3.5.13(typescript@5.5.4)) '@vitejs/plugin-vue': specifier: ^5.0.4 - version: 5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4)) + version: 5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4)) autoprefixer: specifier: ^10.4.19 version: 10.4.20(postcss@8.4.49) eslint: specifier: ^9.9.1 - version: 9.13.0(jiti@2.4.2) + version: 9.13.0(jiti@2.5.1) eslint-config-custom: specifier: workspace:* version: link:../../packages/eslint-config-custom eslint-plugin-turbo: specifier: ^2.5.4 - version: 2.5.4(eslint@9.13.0(jiti@2.4.2))(turbo@2.5.4) + version: 2.5.4(eslint@9.13.0(jiti@2.5.1))(turbo@2.5.4) postcss: specifier: ^8.4.39 version: 8.4.49 @@ -170,7 +170,7 @@ importers: version: 5.5.4 vite: specifier: ^5.4.6 - version: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0) + version: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1) vue-tsc: specifier: ^2.1.6 version: 2.1.6(typescript@5.5.4) @@ -190,19 +190,19 @@ importers: version: 0.9.4(prettier@3.6.2)(typescript@5.8.2) '@astrojs/starlight': specifier: ^0.32.2 - version: 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)) + version: 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)) '@modrinth/assets': specifier: workspace:* version: link:../../packages/assets astro: specifier: ^5.4.1 - version: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0) + version: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0) sharp: specifier: ^0.33.5 version: 0.33.5 starlight-openapi: specifier: ^0.14.0 - version: 0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)))(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0))(openapi-types@12.1.3) + version: 0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)))(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0))(openapi-types@12.1.3) typescript: specifier: ^5.8.2 version: 5.8.2 @@ -284,6 +284,9 @@ importers: pinia: specifier: ^2.1.7 version: 2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)) + pinia-plugin-persistedstate: + specifier: ^4.4.1 + version: 4.4.1(@nuxt/kit@3.17.5(magicast@0.3.5))(@pinia/nuxt@0.5.1(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)))(pinia@2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4))) prettier: specifier: ^3.6.2 version: 3.6.2 @@ -296,6 +299,9 @@ importers: three: specifier: ^0.172.0 version: 0.172.0 + vue-confetti-explosion: + specifier: ^1.0.2 + version: 1.0.2(vue@3.5.13(typescript@5.5.4)) vue-multiselect: specifier: 3.0.0-alpha.2 version: 3.0.0-alpha.2 @@ -317,7 +323,7 @@ importers: version: 6.2.12(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) '@nuxt/devtools': specifier: ^1.3.3 - version: 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4)) + version: 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4)) '@types/dompurify': specifier: ^3.0.5 version: 3.0.5 @@ -332,7 +338,7 @@ importers: version: 3.0.1(@formatjs/intl@2.10.4(typescript@5.5.4)) '@vintl/nuxt': specifier: ^1.9.2 - version: 1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1) + version: 1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1) autoprefixer: specifier: ^10.4.19 version: 10.4.20(postcss@8.4.49) @@ -344,7 +350,7 @@ importers: version: 10.4.2 nuxt: specifier: ^3.14.1592 - version: 3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4))(xml2js@0.6.2) + version: 3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.43.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue-tsc@2.1.6(typescript@5.5.4))(xml2js@0.6.2) postcss: specifier: ^8.4.39 version: 8.4.49 @@ -441,22 +447,22 @@ importers: devDependencies: '@nuxtjs/eslint-config-typescript': specifier: ^12.1.0 - version: 12.1.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + version: 12.1.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@vue/eslint-config-typescript': specifier: ^13.0.0 - version: 13.0.0(eslint-plugin-vue@9.29.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + version: 13.0.0(eslint-plugin-vue@9.29.0(eslint@9.13.0(jiti@2.5.1)))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) eslint-config-prettier: specifier: ^9.1.0 - version: 9.1.0(eslint@9.13.0(jiti@2.4.2)) + version: 9.1.0(eslint@9.13.0(jiti@2.5.1)) eslint-config-turbo: specifier: ^2.0.7 - version: 2.0.7(eslint@9.13.0(jiti@2.4.2)) + version: 2.0.7(eslint@9.13.0(jiti@2.5.1)) eslint-plugin-prettier: specifier: ^5.2.1 - version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(prettier@3.6.2) + version: 5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.5.1)))(eslint@9.13.0(jiti@2.5.1))(prettier@3.6.2) eslint-plugin-unicorn: specifier: ^54.0.0 - version: 54.0.0(eslint@9.13.0(jiti@2.4.2)) + version: 54.0.0(eslint@9.13.0(jiti@2.5.1)) typescript: specifier: ^5.5.3 version: 5.5.4 @@ -4003,6 +4009,9 @@ packages: deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + deep-pick-omit@1.2.1: + resolution: {integrity: sha512-2J6Kc/m3irCeqVG42T+SaUMesaK7oGWaedGnQQK/+O0gYc+2SP5bKh/KKTE7d7SJ+GCA9UUE1GRzh6oDe0EnGw==} + deepmerge@4.3.1: resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} engines: {node: '>=0.10.0'} @@ -6382,6 +6391,20 @@ packages: resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==} engines: {node: '>=6'} + pinia-plugin-persistedstate@4.4.1: + resolution: {integrity: sha512-lmuMPpXla2zJKjxEq34e1E9P9jxkWEhcVwwioCCE0izG45kkTOvQfCzvwhW3i38cvnaWC7T1eRdkd15Re59ldw==} + peerDependencies: + '@nuxt/kit': '>=3.0.0' + '@pinia/nuxt': '>=0.10.0' + pinia: '>=3.0.0' + peerDependenciesMeta: + '@nuxt/kit': + optional: true + '@pinia/nuxt': + optional: true + pinia: + optional: true + pinia@2.1.7: resolution: {integrity: sha512-+C2AHFtcFqjPih0zpYuvof37SFxMQ7OEG2zV9jRI12i9BOy3YQVAHwdKtyyc8pDcDyIc33WCIsZaCFWU7WWxGQ==} peerDependencies: @@ -8273,6 +8296,12 @@ packages: vue-bundle-renderer@2.1.1: resolution: {integrity: sha512-+qALLI5cQncuetYOXp4yScwYvqh8c6SMXee3B+M7oTZxOgtESP0l4j/fXdEJoZ+EdMxkGWIj+aSEyjXkOdmd7g==} + vue-confetti-explosion@1.0.2: + resolution: {integrity: sha512-80OboM3/6BItIoZ6DpNcZFqGpF607kjIVc5af56oKgtFmt5yWehvJeoYhkzYlqxrqdBe0Ko4Ie3bWrmLau+dJw==} + engines: {node: '>=12'} + peerDependencies: + vue: ^3.0.5 + vue-demi@0.14.10: resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==} engines: {node: '>=12'} @@ -8659,12 +8688,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@astrojs/mdx@4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0))': + '@astrojs/mdx@4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0))': dependencies: '@astrojs/markdown-remark': 6.2.0 '@mdx-js/mdx': 3.1.0(acorn@8.14.0) acorn: 8.14.0 - astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0) + astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0) es-module-lexer: 1.6.0 estree-util-visit: 2.0.0 hast-util-to-html: 9.0.5 @@ -8688,16 +8717,16 @@ snapshots: stream-replace-string: 2.0.0 zod: 3.23.8 - '@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0))': + '@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0))': dependencies: - '@astrojs/mdx': 4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)) + '@astrojs/mdx': 4.1.0(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)) '@astrojs/sitemap': 3.2.1 '@pagefind/default-ui': 1.3.0 '@types/hast': 3.0.4 '@types/js-yaml': 4.0.9 '@types/mdast': 4.0.4 - astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0) - astro-expressive-code: 0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)) + astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0) + astro-expressive-code: 0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)) bcp-47: 2.1.0 hast-util-from-html: 2.0.2 hast-util-select: 6.0.2 @@ -9340,16 +9369,16 @@ snapshots: eslint: 8.57.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/eslint-utils@4.4.0(eslint@9.13.0(jiti@2.4.2))': + '@eslint-community/eslint-utils@4.4.0(eslint@9.13.0(jiti@2.5.1))': dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.11.0': {} - '@eslint/compat@1.2.1(eslint@9.13.0(jiti@2.4.2))': + '@eslint/compat@1.2.1(eslint@9.13.0(jiti@2.5.1))': optionalDependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) '@eslint/config-array@0.18.0': dependencies: @@ -9799,12 +9828,12 @@ snapshots: '@nuxt/devalue@2.0.2': {} - '@nuxt/devtools-kit@1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))': + '@nuxt/devtools-kit@1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))': dependencies: '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) '@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) execa: 7.2.0 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) transitivePeerDependencies: - magicast - rollup @@ -9823,13 +9852,13 @@ snapshots: rc9: 2.1.2 semver: 7.7.1 - '@nuxt/devtools@1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))': + '@nuxt/devtools@1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))': dependencies: '@antfu/utils': 0.7.10 - '@nuxt/devtools-kit': 1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)) + '@nuxt/devtools-kit': 1.6.3(magicast@0.3.5)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)) '@nuxt/devtools-wizard': 1.6.3 '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) - '@vue/devtools-core': 7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4)) + '@vue/devtools-core': 7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4)) '@vue/devtools-kit': 7.6.4 birpc: 0.2.19 consola: 3.2.3 @@ -9858,9 +9887,9 @@ snapshots: sirv: 3.0.0 tinyglobby: 0.2.10 unimport: 3.14.4(rollup@4.28.1) - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) - vite-plugin-inspect: 0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)) - vite-plugin-vue-inspector: 5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) + vite-plugin-inspect: 0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)) + vite-plugin-vue-inspector: 5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)) which: 3.0.1 ws: 8.18.0 transitivePeerDependencies: @@ -9870,34 +9899,34 @@ snapshots: - utf-8-validate - vue - '@nuxt/eslint-config@0.5.7(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@nuxt/eslint-config@0.5.7(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@eslint/js': 9.13.0 - '@nuxt/eslint-plugin': 0.5.7(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@stylistic/eslint-plugin': 2.9.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/eslint-plugin': 8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/parser': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) - eslint-config-flat-gitignore: 0.3.0(eslint@9.13.0(jiti@2.4.2)) + '@nuxt/eslint-plugin': 0.5.7(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@stylistic/eslint-plugin': 2.9.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/eslint-plugin': 8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/parser': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) + eslint-config-flat-gitignore: 0.3.0(eslint@9.13.0(jiti@2.5.1)) eslint-flat-config-utils: 0.4.0 - eslint-plugin-import-x: 4.3.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint-plugin-jsdoc: 50.4.3(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-regexp: 2.6.0(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-unicorn: 55.0.0(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.4.2)) + eslint-plugin-import-x: 4.3.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint-plugin-jsdoc: 50.4.3(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-regexp: 2.6.0(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-unicorn: 55.0.0(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.5.1)) globals: 15.11.0 local-pkg: 0.5.1 pathe: 1.1.2 - vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@2.4.2)) + vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - typescript - '@nuxt/eslint-plugin@0.5.7(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@nuxt/eslint-plugin@0.5.7(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/types': 8.10.0 - '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) transitivePeerDependencies: - supports-color - typescript @@ -10002,12 +10031,12 @@ snapshots: - rollup - supports-color - '@nuxt/vite-builder@3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4))': + '@nuxt/vite-builder@3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.43.1)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4))': dependencies: '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) '@rollup/plugin-replace': 6.0.1(rollup@4.28.1) - '@vitejs/plugin-vue': 5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4)) - '@vitejs/plugin-vue-jsx': 4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4)) + '@vitejs/plugin-vue': 5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4)) + '@vitejs/plugin-vue-jsx': 4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4)) autoprefixer: 10.4.20(postcss@8.4.49) clear: 0.1.0 consola: 3.2.3 @@ -10034,9 +10063,9 @@ snapshots: ufo: 1.5.4 unenv: 1.10.0 unplugin: 1.16.0 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) - vite-node: 2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) - vite-plugin-checker: 0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4)) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) + vite-node: 2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) + vite-plugin-checker: 0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue-tsc@2.1.6(typescript@5.5.4)) vue: 3.5.13(typescript@5.5.4) vue-bundle-renderer: 2.1.1 transitivePeerDependencies: @@ -10061,31 +10090,31 @@ snapshots: - vti - vue-tsc - '@nuxtjs/eslint-config-typescript@12.1.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@nuxtjs/eslint-config-typescript@12.1.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: - '@nuxtjs/eslint-config': 12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.2)) - '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.4.2)) + '@nuxtjs/eslint-config': 12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.5.1)) + '@typescript-eslint/eslint-plugin': 6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.5.1)) transitivePeerDependencies: - eslint-import-resolver-node - eslint-import-resolver-webpack - supports-color - typescript - '@nuxtjs/eslint-config@12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.2))': + '@nuxtjs/eslint-config@12.0.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.5.1))': dependencies: - eslint: 9.13.0(jiti@2.4.2) - eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.2)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-n: 15.7.0(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-node: 11.1.0(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-promise: 6.4.0(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-unicorn: 44.0.2(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.5.1)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.5.1)))(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-n: 15.7.0(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-node: 11.1.0(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-promise: 6.4.0(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-unicorn: 44.0.2(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.5.1)) local-pkg: 0.4.3 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -10535,10 +10564,10 @@ snapshots: '@stripe/stripe-js@7.3.1': {} - '@stylistic/eslint-plugin@2.9.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@stylistic/eslint-plugin@2.9.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: - '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) eslint-visitor-keys: 4.1.0 espree: 10.2.0 estraverse: 5.3.0 @@ -10805,16 +10834,16 @@ snapshots: dependencies: '@types/node': 20.14.11 - '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@6.21.0(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@typescript-eslint/scope-manager': 6.21.0 - '@typescript-eslint/type-utils': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/type-utils': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/utils': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 @@ -10825,15 +10854,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@7.16.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@typescript-eslint/scope-manager': 7.16.1 - '@typescript-eslint/type-utils': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/utils': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/type-utils': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/utils': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@typescript-eslint/visitor-keys': 7.16.1 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 @@ -10843,15 +10872,15 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@8.10.0(@typescript-eslint/parser@8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/parser': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@typescript-eslint/scope-manager': 8.10.0 - '@typescript-eslint/type-utils': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/type-utils': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.10.0 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 @@ -10861,40 +10890,40 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 6.21.0 debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/scope-manager': 7.16.1 '@typescript-eslint/types': 7.16.1 '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.4) '@typescript-eslint/visitor-keys': 7.16.1 debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/parser@8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/scope-manager': 8.10.0 '@typescript-eslint/types': 8.10.0 '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.10.0 debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -10915,34 +10944,34 @@ snapshots: '@typescript-eslint/types': 8.10.0 '@typescript-eslint/visitor-keys': 8.10.0 - '@typescript-eslint/type-utils@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/type-utils@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - '@typescript-eslint/utils': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/utils': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/type-utils@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.4) - '@typescript-eslint/utils': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/utils': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/type-utils@8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) debug: 4.4.0(supports-color@9.4.0) ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: @@ -11002,38 +11031,38 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/utils@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) '@types/json-schema': 7.0.15 '@types/semver': 7.5.8 '@typescript-eslint/scope-manager': 6.21.0 '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) semver: 7.7.1 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/utils@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) '@typescript-eslint/scope-manager': 7.16.1 '@typescript-eslint/types': 7.16.1 '@typescript-eslint/typescript-estree': 7.16.1(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@typescript-eslint/utils@8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) '@typescript-eslint/scope-manager': 8.10.0 '@typescript-eslint/types': 8.10.0 '@typescript-eslint/typescript-estree': 8.10.0(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) transitivePeerDependencies: - supports-color - typescript @@ -11114,12 +11143,12 @@ snapshots: '@formatjs/intl': 2.10.4(typescript@5.5.4) intl-messageformat: 10.5.14 - '@vintl/nuxt@1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)': + '@vintl/nuxt@1.9.2(@vue/compiler-core@3.5.13)(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)': dependencies: '@formatjs/intl': 2.10.4(typescript@5.5.4) '@formatjs/intl-localematcher': 0.5.4 '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) - '@vintl/unplugin': 2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1) + '@vintl/unplugin': 2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1) '@vintl/vintl': 4.4.1(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)) astring: 1.8.6 consola: 3.2.3 @@ -11170,7 +11199,7 @@ snapshots: - ts-jest - vue - '@vintl/unplugin@2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)': + '@vintl/unplugin@2.0.0(@vue/compiler-core@3.5.13)(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))(webpack@5.92.1)': dependencies: '@formatjs/cli-lib': 6.4.2(@vue/compiler-core@3.5.13)(vue@3.5.13(typescript@5.5.4)) '@formatjs/icu-messageformat-parser': 2.7.8 @@ -11181,7 +11210,7 @@ snapshots: unplugin: 1.16.0 optionalDependencies: rollup: 4.28.1 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) webpack: 5.92.1 transitivePeerDependencies: - '@glimmer/env' @@ -11205,24 +11234,24 @@ snapshots: transitivePeerDependencies: - typescript - '@vitejs/plugin-vue-jsx@4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))': + '@vitejs/plugin-vue-jsx@4.1.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))': dependencies: '@babel/core': 7.26.0 '@babel/plugin-transform-typescript': 7.26.3(@babel/core@7.26.0) '@vue/babel-plugin-jsx': 1.2.5(@babel/core@7.26.0) - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) vue: 3.5.13(typescript@5.5.4) transitivePeerDependencies: - supports-color - '@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))': + '@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))': dependencies: - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) vue: 3.5.13(typescript@5.5.4) - '@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))': + '@vitejs/plugin-vue@5.2.1(vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))': dependencies: - vite: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1) vue: 3.5.13(typescript@5.5.4) '@volar/kit@2.4.11(typescript@5.8.2)': @@ -11367,14 +11396,14 @@ snapshots: '@vue/devtools-api@6.6.4': {} - '@vue/devtools-core@7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4))': + '@vue/devtools-core@7.6.4(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4))': dependencies: '@vue/devtools-kit': 7.6.4 '@vue/devtools-shared': 7.6.7 mitt: 3.0.1 nanoid: 3.3.7 pathe: 1.1.2 - vite-hot-client: 0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)) + vite-hot-client: 0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)) vue: 3.5.13(typescript@5.5.4) transitivePeerDependencies: - vite @@ -11393,13 +11422,13 @@ snapshots: dependencies: rfdc: 1.4.1 - '@vue/eslint-config-typescript@13.0.0(eslint-plugin-vue@9.29.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4)': + '@vue/eslint-config-typescript@13.0.0(eslint-plugin-vue@9.29.0(eslint@9.13.0(jiti@2.5.1)))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4)': dependencies: - '@typescript-eslint/eslint-plugin': 7.16.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) - eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.4.2)) - vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@2.4.2)) + '@typescript-eslint/eslint-plugin': 7.16.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) + eslint-plugin-vue: 9.29.0(eslint@9.13.0(jiti@2.5.1)) + vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@2.5.1)) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -11823,12 +11852,12 @@ snapshots: astring@1.8.6: {} - astro-expressive-code@0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)): + astro-expressive-code@0.40.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)): dependencies: - astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0) + astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0) rehype-expressive-code: 0.40.2 - astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0): + astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0): dependencies: '@astrojs/compiler': 2.10.4 '@astrojs/internal-helpers': 0.6.0 @@ -11880,8 +11909,8 @@ snapshots: unist-util-visit: 5.0.0 unstorage: 1.15.0(db0@0.3.2) vfile: 6.0.3 - vite: 6.2.0(@types/node@22.4.1)(jiti@2.4.2)(sass@1.77.6)(terser@5.42.0)(yaml@2.8.0) - vitefu: 1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.4.2)(sass@1.77.6)(terser@5.42.0)(yaml@2.8.0)) + vite: 6.2.0(@types/node@22.4.1)(jiti@2.5.1)(sass@1.77.6)(terser@5.43.1)(yaml@2.8.0) + vitefu: 1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.5.1)(sass@1.77.6)(terser@5.43.1)(yaml@2.8.0)) which-pm: 3.0.1 xxhash-wasm: 1.1.0 yargs-parser: 21.1.1 @@ -12457,6 +12486,8 @@ snapshots: deep-is@0.1.4: {} + deep-pick-omit@1.2.1: {} + deepmerge@4.3.1: {} default-browser-id@5.0.0: {} @@ -12494,8 +12525,7 @@ snapshots: destr@2.0.3: {} - destr@2.0.5: - optional: true + destr@2.0.5: {} destroy@1.2.0: {} @@ -12857,27 +12887,27 @@ snapshots: escape-string-regexp@5.0.0: {} - eslint-config-flat-gitignore@0.3.0(eslint@9.13.0(jiti@2.4.2)): + eslint-config-flat-gitignore@0.3.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - '@eslint/compat': 1.2.1(eslint@9.13.0(jiti@2.4.2)) - eslint: 9.13.0(jiti@2.4.2) + '@eslint/compat': 1.2.1(eslint@9.13.0(jiti@2.5.1)) + eslint: 9.13.0(jiti@2.5.1) find-up-simple: 1.0.0 - eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)): + eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) - eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.2)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2)): + eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.5.1)))(eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.5.1)))(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-n: 15.7.0(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-promise: 6.4.0(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-n: 15.7.0(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-promise: 6.4.0(eslint@9.13.0(jiti@2.5.1)) - eslint-config-turbo@2.0.7(eslint@9.13.0(jiti@2.4.2)): + eslint-config-turbo@2.0.7(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) - eslint-plugin-turbo: 2.0.7(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-plugin-turbo: 2.0.7(eslint@9.13.0(jiti@2.5.1)) eslint-flat-config-utils@0.4.0: dependencies: @@ -12891,13 +12921,13 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.2)): + eslint-import-resolver-typescript@3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.5.1)): dependencies: debug: 4.4.0(supports-color@9.4.0) enhanced-resolve: 5.17.1 - eslint: 9.13.0(jiti@2.4.2) - eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.2)) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.5.1)) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1)) fast-glob: 3.3.2 get-tsconfig: 4.7.5 is-core-module: 2.15.0 @@ -12908,45 +12938,45 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.2)): + eslint-module-utils@2.8.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.4.2)) + eslint-import-resolver-typescript: 3.6.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-plugin-import@2.29.1)(eslint@9.13.0(jiti@2.5.1)) transitivePeerDependencies: - supports-color - eslint-module-utils@2.8.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0(jiti@2.4.2)): + eslint-module-utils@2.8.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0(jiti@2.5.1)): dependencies: debug: 3.2.7 optionalDependencies: - '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) - eslint: 9.13.0(jiti@2.4.2) + '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) + eslint: 9.13.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: - supports-color - eslint-plugin-es@3.0.1(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-es@3.0.1(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-utils: 2.1.0 regexpp: 3.2.0 - eslint-plugin-es@4.1.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-es@4.1.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-utils: 2.1.0 regexpp: 3.2.0 - eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4): + eslint-plugin-import-x@4.3.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4): dependencies: - '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/utils': 8.10.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) debug: 4.4.0(supports-color@9.4.0) doctrine: 3.0.0 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 get-tsconfig: 4.7.5 is-glob: 4.0.3 @@ -12958,7 +12988,7 @@ snapshots: - supports-color - typescript - eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-typescript@3.6.1)(eslint@9.13.0(jiti@2.5.1)): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -12966,9 +12996,9 @@ snapshots: array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0(jiti@2.4.2)) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.15.0 is-glob: 4.0.3 @@ -12979,13 +13009,13 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/parser': 6.21.0(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint@9.13.0(jiti@2.5.1)): dependencies: array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -12993,9 +13023,9 @@ snapshots: array.prototype.flatmap: 1.3.2 debug: 3.2.7 doctrine: 2.1.0 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0(jiti@2.4.2)) + eslint-module-utils: 2.8.1(@typescript-eslint/parser@7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4))(eslint-import-resolver-node@0.3.9)(eslint@9.13.0(jiti@2.5.1)) hasown: 2.0.2 is-core-module: 2.15.0 is-glob: 4.0.3 @@ -13006,20 +13036,20 @@ snapshots: semver: 6.3.1 tsconfig-paths: 3.15.0 optionalDependencies: - '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.4.2))(typescript@5.5.4) + '@typescript-eslint/parser': 7.16.1(eslint@9.13.0(jiti@2.5.1))(typescript@5.5.4) transitivePeerDependencies: - eslint-import-resolver-typescript - eslint-import-resolver-webpack - supports-color - eslint-plugin-jsdoc@50.4.3(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-jsdoc@50.4.3(eslint@9.13.0(jiti@2.5.1)): dependencies: '@es-joy/jsdoccomment': 0.49.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 debug: 4.4.0(supports-color@9.4.0) escape-string-regexp: 4.0.0 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) espree: 10.2.0 esquery: 1.6.0 parse-imports: 2.2.1 @@ -13029,71 +13059,71 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-n@15.7.0(eslint@9.13.0(jiti@2.5.1)): dependencies: builtins: 5.1.0 - eslint: 9.13.0(jiti@2.4.2) - eslint-plugin-es: 4.1.0(eslint@9.13.0(jiti@2.4.2)) - eslint-utils: 3.0.0(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-plugin-es: 4.1.0(eslint@9.13.0(jiti@2.5.1)) + eslint-utils: 3.0.0(eslint@9.13.0(jiti@2.5.1)) ignore: 5.3.1 is-core-module: 2.15.0 minimatch: 3.1.2 resolve: 1.22.8 semver: 7.7.1 - eslint-plugin-node@11.1.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-node@11.1.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) - eslint-plugin-es: 3.0.1(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-plugin-es: 3.0.1(eslint@9.13.0(jiti@2.5.1)) eslint-utils: 2.1.0 ignore: 5.3.1 minimatch: 3.1.2 resolve: 1.22.8 semver: 6.3.1 - eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.4.2)))(eslint@9.13.0(jiti@2.4.2))(prettier@3.6.2): + eslint-plugin-prettier@5.2.1(@types/eslint@9.6.1)(eslint-config-prettier@9.1.0(eslint@9.13.0(jiti@2.5.1)))(eslint@9.13.0(jiti@2.5.1))(prettier@3.6.2): dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) prettier: 3.6.2 prettier-linter-helpers: 1.0.0 synckit: 0.9.1 optionalDependencies: '@types/eslint': 9.6.1 - eslint-config-prettier: 9.1.0(eslint@9.13.0(jiti@2.4.2)) + eslint-config-prettier: 9.1.0(eslint@9.13.0(jiti@2.5.1)) - eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-promise@6.4.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) - eslint-plugin-regexp@2.6.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-regexp@2.6.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.11.0 comment-parser: 1.4.1 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) jsdoc-type-pratt-parser: 4.1.0 refa: 0.12.1 regexp-ast-analysis: 0.7.1 scslre: 0.3.0 - eslint-plugin-turbo@2.0.7(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-turbo@2.0.7(eslint@9.13.0(jiti@2.5.1)): dependencies: dotenv: 16.0.3 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) - eslint-plugin-turbo@2.5.4(eslint@9.13.0(jiti@2.4.2))(turbo@2.5.4): + eslint-plugin-turbo@2.5.4(eslint@9.13.0(jiti@2.5.1))(turbo@2.5.4): dependencies: dotenv: 16.0.3 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) turbo: 2.5.4 - eslint-plugin-unicorn@44.0.2(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-unicorn@44.0.2(eslint@9.13.0(jiti@2.5.1)): dependencies: '@babel/helper-validator-identifier': 7.25.9 ci-info: 3.9.0 clean-regexp: 1.0.0 - eslint: 9.13.0(jiti@2.4.2) - eslint-utils: 3.0.0(eslint@9.13.0(jiti@2.4.2)) + eslint: 9.13.0(jiti@2.5.1) + eslint-utils: 3.0.0(eslint@9.13.0(jiti@2.5.1)) esquery: 1.6.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 @@ -13105,15 +13135,15 @@ snapshots: semver: 7.7.1 strip-indent: 3.0.0 - eslint-plugin-unicorn@54.0.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-unicorn@54.0.0(eslint@9.13.0(jiti@2.5.1)): dependencies: '@babel/helper-validator-identifier': 7.25.9 - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) '@eslint/eslintrc': 3.1.0 ci-info: 4.0.0 clean-regexp: 1.0.0 core-js-compat: 3.37.1 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) esquery: 1.6.0 indent-string: 4.0.0 is-builtin-module: 3.2.1 @@ -13127,14 +13157,14 @@ snapshots: transitivePeerDependencies: - supports-color - eslint-plugin-unicorn@55.0.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-unicorn@55.0.0(eslint@9.13.0(jiti@2.5.1)): dependencies: '@babel/helper-validator-identifier': 7.25.9 - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) ci-info: 4.0.0 clean-regexp: 1.0.0 core-js-compat: 3.37.1 - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) esquery: 1.6.0 globals: 15.11.0 indent-string: 4.0.0 @@ -13147,16 +13177,16 @@ snapshots: semver: 7.6.3 strip-indent: 3.0.0 - eslint-plugin-vue@9.29.0(eslint@9.13.0(jiti@2.4.2)): + eslint-plugin-vue@9.29.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) - eslint: 9.13.0(jiti@2.4.2) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) + eslint: 9.13.0(jiti@2.5.1) globals: 13.24.0 natural-compare: 1.4.0 nth-check: 2.1.1 postcss-selector-parser: 6.1.2 semver: 7.6.3 - vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@2.4.2)) + vue-eslint-parser: 9.4.3(eslint@9.13.0(jiti@2.5.1)) xml-name-validator: 4.0.0 transitivePeerDependencies: - supports-color @@ -13181,9 +13211,9 @@ snapshots: dependencies: eslint-visitor-keys: 1.3.0 - eslint-utils@3.0.0(eslint@9.13.0(jiti@2.4.2)): + eslint-utils@3.0.0(eslint@9.13.0(jiti@2.5.1)): dependencies: - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-visitor-keys: 2.1.0 eslint-visitor-keys@1.3.0: {} @@ -13237,9 +13267,9 @@ snapshots: transitivePeerDependencies: - supports-color - eslint@9.13.0(jiti@2.4.2): + eslint@9.13.0(jiti@2.5.1): dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.4.2)) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.13.0(jiti@2.5.1)) '@eslint-community/regexpp': 4.11.0 '@eslint/config-array': 0.18.0 '@eslint/core': 0.7.0 @@ -13275,7 +13305,7 @@ snapshots: optionator: 0.9.4 text-table: 0.2.0 optionalDependencies: - jiti: 2.4.2 + jiti: 2.5.1 transitivePeerDependencies: - supports-color @@ -13767,7 +13797,7 @@ snapshots: cookie-es: 1.2.2 crossws: 0.3.4 defu: 6.1.4 - destr: 2.0.3 + destr: 2.0.5 iron-webcrypto: 1.2.1 node-mock-http: 1.0.0 radix3: 1.1.2 @@ -14317,7 +14347,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 22.4.1 + '@types/node': 20.14.11 merge-stream: 2.0.0 supports-color: 8.1.1 optional: true @@ -15354,14 +15384,14 @@ snapshots: nuxi@3.16.0: {} - nuxt@3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4))(xml2js@0.6.2): + nuxt@3.14.1592(@parcel/watcher@2.4.1)(@types/node@20.14.11)(eslint@8.57.0)(ioredis@5.4.1)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.43.1)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue-tsc@2.1.6(typescript@5.5.4))(xml2js@0.6.2): dependencies: '@nuxt/devalue': 2.0.2 - '@nuxt/devtools': 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue@3.5.13(typescript@5.5.4)) + '@nuxt/devtools': 1.6.3(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue@3.5.13(typescript@5.5.4)) '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) '@nuxt/schema': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) '@nuxt/telemetry': 2.6.0(magicast@0.3.5)(rollup@4.28.1) - '@nuxt/vite-builder': 3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.42.0)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4)) + '@nuxt/vite-builder': 3.14.1592(@types/node@20.14.11)(eslint@8.57.0)(magicast@0.3.5)(optionator@0.9.4)(rollup@4.28.1)(sass@1.77.6)(terser@5.43.1)(typescript@5.5.4)(vue-tsc@2.1.6(typescript@5.5.4))(vue@3.5.13(typescript@5.5.4)) '@unhead/dom': 1.11.13 '@unhead/shared': 1.11.13 '@unhead/ssr': 1.11.13 @@ -15754,6 +15784,16 @@ snapshots: pify@4.0.1: {} + pinia-plugin-persistedstate@4.4.1(@nuxt/kit@3.17.5(magicast@0.3.5))(@pinia/nuxt@0.5.1(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)))(pinia@2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4))): + dependencies: + deep-pick-omit: 1.2.1 + defu: 6.1.4 + destr: 2.0.5 + optionalDependencies: + '@nuxt/kit': 3.17.5(magicast@0.3.5) + '@pinia/nuxt': 0.5.1(magicast@0.3.5)(rollup@4.28.1)(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)) + pinia: 2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)) + pinia@2.1.7(typescript@5.5.4)(vue@3.5.13(typescript@5.5.4)): dependencies: '@vue/devtools-api': 6.6.4 @@ -16773,12 +16813,12 @@ snapshots: standard-as-callback@2.1.0: {} - starlight-openapi@0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)))(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0))(openapi-types@12.1.3): + starlight-openapi@0.14.0(@astrojs/markdown-remark@6.2.0)(@astrojs/starlight@0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)))(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0))(openapi-types@12.1.3): dependencies: '@astrojs/markdown-remark': 6.2.0 - '@astrojs/starlight': 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0)) + '@astrojs/starlight': 0.32.2(astro@5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0)) '@readme/openapi-parser': 2.5.0(openapi-types@12.1.3) - astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.4.2)(rollup@4.34.9)(sass@1.77.6)(terser@5.42.0)(typescript@5.8.2)(yaml@2.8.0) + astro: 5.4.1(@types/node@22.4.1)(db0@0.3.2)(jiti@2.5.1)(rollup@4.34.9)(sass@1.77.6)(terser@5.43.1)(typescript@5.8.2)(yaml@2.8.0) github-slugger: 2.0.0 url-template: 3.1.1 transitivePeerDependencies: @@ -17549,17 +17589,17 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-hot-client@0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)): + vite-hot-client@0.2.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)): dependencies: - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) - vite-node@2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0): + vite-node@2.1.8(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1): dependencies: cac: 6.7.14 debug: 4.4.0(supports-color@9.4.0) es-module-lexer: 1.5.4 pathe: 1.1.2 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) transitivePeerDependencies: - '@types/node' - less @@ -17571,7 +17611,7 @@ snapshots: - supports-color - terser - vite-plugin-checker@0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0))(vue-tsc@2.1.6(typescript@5.5.4)): + vite-plugin-checker@0.8.0(eslint@8.57.0)(optionator@0.9.4)(typescript@5.5.4)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1))(vue-tsc@2.1.6(typescript@5.5.4)): dependencies: '@babel/code-frame': 7.26.2 ansi-escapes: 4.3.2 @@ -17583,7 +17623,7 @@ snapshots: npm-run-path: 4.0.1 strip-ansi: 6.0.1 tiny-invariant: 1.3.3 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) vscode-languageclient: 7.0.0 vscode-languageserver: 7.0.0 vscode-languageserver-textdocument: 1.0.12 @@ -17594,7 +17634,7 @@ snapshots: typescript: 5.5.4 vue-tsc: 2.1.6(typescript@5.5.4) - vite-plugin-inspect@0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)): + vite-plugin-inspect@0.8.9(@nuxt/kit@3.14.1592(magicast@0.3.5)(rollup@4.28.1))(rollup@4.28.1)(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)): dependencies: '@antfu/utils': 0.7.10 '@rollup/pluginutils': 5.1.3(rollup@4.28.1) @@ -17605,14 +17645,14 @@ snapshots: perfect-debounce: 1.0.0 picocolors: 1.1.1 sirv: 3.0.0 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) optionalDependencies: '@nuxt/kit': 3.14.1592(magicast@0.3.5)(rollup@4.28.1) transitivePeerDependencies: - rollup - supports-color - vite-plugin-vue-inspector@5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0)): + vite-plugin-vue-inspector@5.1.3(vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1)): dependencies: '@babel/core': 7.26.0 '@babel/plugin-proposal-decorators': 7.24.7(@babel/core@7.26.0) @@ -17623,7 +17663,7 @@ snapshots: '@vue/compiler-dom': 3.5.13 kolorist: 1.8.0 magic-string: 0.30.14 - vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0) + vite: 5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1) transitivePeerDependencies: - supports-color @@ -17644,7 +17684,7 @@ snapshots: terser: 5.43.1 optional: true - vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.42.0): + vite@5.4.11(@types/node@20.14.11)(sass@1.77.6)(terser@5.43.1): dependencies: esbuild: 0.21.5 postcss: 8.4.49 @@ -17653,9 +17693,9 @@ snapshots: '@types/node': 20.14.11 fsevents: 2.3.3 sass: 1.77.6 - terser: 5.42.0 + terser: 5.43.1 - vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.42.0): + vite@5.4.11(@types/node@22.4.1)(sass@1.77.6)(terser@5.43.1): dependencies: esbuild: 0.21.5 postcss: 8.4.49 @@ -17664,9 +17704,9 @@ snapshots: '@types/node': 22.4.1 fsevents: 2.3.3 sass: 1.77.6 - terser: 5.42.0 + terser: 5.43.1 - vite@6.2.0(@types/node@22.4.1)(jiti@2.4.2)(sass@1.77.6)(terser@5.42.0)(yaml@2.8.0): + vite@6.2.0(@types/node@22.4.1)(jiti@2.5.1)(sass@1.77.6)(terser@5.43.1)(yaml@2.8.0): dependencies: esbuild: 0.25.0 postcss: 8.5.3 @@ -17674,14 +17714,14 @@ snapshots: optionalDependencies: '@types/node': 22.4.1 fsevents: 2.3.3 - jiti: 2.4.2 + jiti: 2.5.1 sass: 1.77.6 - terser: 5.42.0 + terser: 5.43.1 yaml: 2.8.0 - vitefu@1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.4.2)(sass@1.77.6)(terser@5.42.0)(yaml@2.8.0)): + vitefu@1.0.6(vite@6.2.0(@types/node@22.4.1)(jiti@2.5.1)(sass@1.77.6)(terser@5.43.1)(yaml@2.8.0)): optionalDependencies: - vite: 6.2.0(@types/node@22.4.1)(jiti@2.4.2)(sass@1.77.6)(terser@5.42.0)(yaml@2.8.0) + vite: 6.2.0(@types/node@22.4.1)(jiti@2.5.1)(sass@1.77.6)(terser@5.43.1)(yaml@2.8.0) volar-service-css@0.0.62(@volar/language-service@2.4.11): dependencies: @@ -17805,16 +17845,20 @@ snapshots: dependencies: ufo: 1.5.4 + vue-confetti-explosion@1.0.2(vue@3.5.13(typescript@5.5.4)): + dependencies: + vue: 3.5.13(typescript@5.5.4) + vue-demi@0.14.10(vue@3.5.13(typescript@5.5.4)): dependencies: vue: 3.5.13(typescript@5.5.4) vue-devtools-stub@0.1.0: {} - vue-eslint-parser@9.4.3(eslint@9.13.0(jiti@2.4.2)): + vue-eslint-parser@9.4.3(eslint@9.13.0(jiti@2.5.1)): dependencies: debug: 4.4.0(supports-color@9.4.0) - eslint: 9.13.0(jiti@2.4.2) + eslint: 9.13.0(jiti@2.5.1) eslint-scope: 7.2.2 eslint-visitor-keys: 3.4.3 espree: 9.6.1 From 1c89b84314ae5f24292da5d8afea33ceeabdca7c Mon Sep 17 00:00:00 2001 From: jade Date: Thu, 31 Jul 2025 12:50:33 -0500 Subject: [PATCH 3/8] fix(moderation): Replace dead modpack link with a valid one in side-types message (#4095) --- .../moderation/data/messages/side-types/inaccurate-modpack.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/moderation/data/messages/side-types/inaccurate-modpack.md b/packages/moderation/data/messages/side-types/inaccurate-modpack.md index dccfba6a7..2c66bdec3 100644 --- a/packages/moderation/data/messages/side-types/inaccurate-modpack.md +++ b/packages/moderation/data/messages/side-types/inaccurate-modpack.md @@ -4,7 +4,7 @@ Per section 5.1 of %RULES%, it is important that the metadata of your projects i For a brief rundown of how this works: -- Some modpacks can be client-side, usually aimed at providing utility and optimization while allowing the player to join an unmodded server, for instance, [Fabulously Optimized](https://modrinth.com/modpack/fabulously-optimized). -- Most other modpacks that change how the game is played are going to be required on both the client and server, like the modpack [Dying Light](https://modrinth.com/modpack/dying-light). +- Some modpacks can be client-side, usually aimed at providing utility and optimization while allowing the player to join an unmodded server, for instance, [Fabulously Optimized](https://modrinth.com/project/1KVo5zza). +- Most other modpacks that change how the game is played are going to be required on both the client and server, like the modpack [Aged](https://modrinth.com/project/i4XHCd7Q). When in doubt, test for yourself or check the requirements of the mods in your pack. From 3a20e15340f741090667823b028eb382f3f4af7e Mon Sep 17 00:00:00 2001 From: coolbot <76798835+coolbot100s@users.noreply.github.com> Date: Fri, 1 Aug 2025 13:21:28 -0700 Subject: [PATCH 4/8] Coolbot/moderation updates aug1 (#4103) * oop, all commas! * Only show slug stuff when needed. * Move status alerts to top of message, getting rid of separators. * redist libs message altered, and now shows on plugins too * Update versions.ts remove unnecessary import Signed-off-by: coolbot <76798835+coolbot100s@users.noreply.github.com> * Tweak summary formatting msg * Update license messages to use flink * reorder link text to match the settings page * add Description clarity button --------- Signed-off-by: coolbot <76798835+coolbot100s@users.noreply.github.com> --- .../messages/checklist-text/links/base.md | 4 ++-- .../checklist-text/title-slug/slug.md | 3 +++ .../checklist-text/title-slug/title.md | 1 + .../data/messages/description/clarity.md | 7 +++++++ .../messages/description/headers-as-body.md | 2 +- .../data/messages/description/image-only.md | 2 +- .../description/insufficient-packs.md | 2 +- .../description/insufficient-projects.md | 2 +- .../data/messages/description/insufficient.md | 2 +- .../data/messages/description/non-english.md | 2 +- .../messages/description/non-standard-text.md | 2 +- .../data/messages/gallery/not-relevant.md | 2 +- .../data/messages/license/invalid_link.md | 4 ++-- .../data/messages/license/no_source-fork.md | 2 +- .../data/messages/license/no_source.md | 2 +- .../moderation/data/messages/links/misused.md | 2 +- .../data/messages/links/not_accessible.md | 2 +- .../data/messages/reupload/reupload.md | 2 +- .../messages/status-alerts/account_issues.md | 2 -- .../status-alerts/automod_confusion.md | 2 +- .../data/messages/status-alerts/fixed.md | 5 ++--- .../data/messages/status-alerts/private.md | 4 +--- .../data/messages/summary/formatting.md | 4 ++-- .../data/messages/summary/insufficient.md | 2 +- .../data/messages/summary/non-english.md | 2 +- .../data/messages/summary/repeat-title.md | 2 +- .../versions/alternate_versions-additional.md | 2 +- .../alternate_versions-server-additional.md | 2 +- .../versions/alternate_versions-zip.md | 2 +- .../versions/incorrect_additional_files.md | 2 +- .../data/messages/versions/redist_libs.md | 2 +- .../moderation/data/stages/description.ts | 9 ++++++++ .../moderation/data/stages/status-alerts.ts | 8 +++---- packages/moderation/data/stages/title-slug.ts | 21 ++++++++++++++++++- packages/moderation/data/stages/versions.ts | 4 ++-- packages/moderation/utils.ts | 7 ++++--- 36 files changed, 81 insertions(+), 46 deletions(-) create mode 100644 packages/moderation/data/messages/checklist-text/title-slug/slug.md create mode 100644 packages/moderation/data/messages/checklist-text/title-slug/title.md create mode 100644 packages/moderation/data/messages/description/clarity.md diff --git a/packages/moderation/data/messages/checklist-text/links/base.md b/packages/moderation/data/messages/checklist-text/links/base.md index 9b12a8e9e..caa71614a 100644 --- a/packages/moderation/data/messages/checklist-text/links/base.md +++ b/packages/moderation/data/messages/checklist-text/links/base.md @@ -1,4 +1,4 @@ -**Discord:** %PROJECT_DISCORD_URL% \ **Issues:** %PROJECT_ISSUES_URL% \ **Source:** %PROJECT_SOURCE_URL% \ -**Wiki:** %PROJECT_WIKI_URL% +**Wiki:** %PROJECT_WIKI_URL% \ +**Discord:** %PROJECT_DISCORD_URL% diff --git a/packages/moderation/data/messages/checklist-text/title-slug/slug.md b/packages/moderation/data/messages/checklist-text/title-slug/slug.md new file mode 100644 index 000000000..52e2fa281 --- /dev/null +++ b/packages/moderation/data/messages/checklist-text/title-slug/slug.md @@ -0,0 +1,3 @@ +**Slug:** `%PROJECT_SLUG%`
+ +**Title issues?** diff --git a/packages/moderation/data/messages/checklist-text/title-slug/title.md b/packages/moderation/data/messages/checklist-text/title-slug/title.md new file mode 100644 index 000000000..6901e7eb6 --- /dev/null +++ b/packages/moderation/data/messages/checklist-text/title-slug/title.md @@ -0,0 +1 @@ +**Title:** %PROJECT_TITLE%
diff --git a/packages/moderation/data/messages/description/clarity.md b/packages/moderation/data/messages/description/clarity.md new file mode 100644 index 000000000..8c59da9dd --- /dev/null +++ b/packages/moderation/data/messages/description/clarity.md @@ -0,0 +1,7 @@ +## Description Clarity + +Per section 2 of %RULES% It's important that your Description accurately and honestly represents the content of your project. +Currently, some elements in your Description may be confusing or misleading. +Please edit your description to ensure it accurately represents the current functionality of your project. +Avoid making hyperbolic claims that could misrepresent the facts of your project. +Ensure that your Description is accurate and not likely to confuse users. diff --git a/packages/moderation/data/messages/description/headers-as-body.md b/packages/moderation/data/messages/description/headers-as-body.md index ded6925db..78e8366f6 100644 --- a/packages/moderation/data/messages/description/headers-as-body.md +++ b/packages/moderation/data/messages/description/headers-as-body.md @@ -1,6 +1,6 @@ ## Description Accessibility -In accordance with section 2.2 of [Modrinth's Content Rules](https://modrinth.com/legal/rules) we request that `# header`s not be used as body text. +In accordance with section 2.2 of %RULES%, we request that `# header`s not be used as body text. Headers are interpreted differently by screen-readers and thus should generally only be used for things like separating sections of your Description. diff --git a/packages/moderation/data/messages/description/image-only.md b/packages/moderation/data/messages/description/image-only.md index d827f9902..57781986e 100644 --- a/packages/moderation/data/messages/description/image-only.md +++ b/packages/moderation/data/messages/description/image-only.md @@ -1,6 +1,6 @@ ## Image Descriptions -In accordance with section 2.2 of [Modrinth's Content Rules](https://modrinth.com/legal/rules) we ask that you provide a text alternative to your current Description. +In accordance with section 2.2 of %RULES%, we ask that you provide a text alternative to your current Description. It is important that your Description contains enough detail about your project that a user can have a full understanding of it from text alone. diff --git a/packages/moderation/data/messages/description/insufficient-packs.md b/packages/moderation/data/messages/description/insufficient-packs.md index fdd264787..a6467057f 100644 --- a/packages/moderation/data/messages/description/insufficient-packs.md +++ b/packages/moderation/data/messages/description/insufficient-packs.md @@ -1,6 +1,6 @@ ## Insufficient Description -Per section 2.1 of [Modrinth's Content Rules](https://modrinth.com/legal/rules#general-expectations) your project's Description should clearly inform the reader of the content, purpose, and appeal of your project. +Per section 2.1 of %RULES%, your project's Description should clearly inform the reader of the content, purpose, and appeal of your project. Currently, it looks like there are some missing details. diff --git a/packages/moderation/data/messages/description/insufficient-projects.md b/packages/moderation/data/messages/description/insufficient-projects.md index 18f8c4e68..9157b8301 100644 --- a/packages/moderation/data/messages/description/insufficient-projects.md +++ b/packages/moderation/data/messages/description/insufficient-projects.md @@ -1,6 +1,6 @@ ## Insufficient Description -Per section 2.1 of [Modrinth's Content Rules](https://modrinth.com/legal/rules#general-expectations) your project's Description should clearly inform the reader of the content, purpose, and appeal of your project. +Per section 2.1 of %RULES%, your project's Description should clearly inform the reader of the content, purpose, and appeal of your project. Currently, it looks like there are some missing details. diff --git a/packages/moderation/data/messages/description/insufficient.md b/packages/moderation/data/messages/description/insufficient.md index f86ded144..cd8ebc8fe 100644 --- a/packages/moderation/data/messages/description/insufficient.md +++ b/packages/moderation/data/messages/description/insufficient.md @@ -1,6 +1,6 @@ ## Insufficient Description -Per section 2.1 of %RULES% your project's Description should clearly inform the reader of the content, purpose, and appeal of your project. +Per section 2.1 of %RULES%, your project's Description should clearly inform the reader of the content, purpose, and appeal of your project. Currently, it looks like there are some missing details. %EXPLAINER% diff --git a/packages/moderation/data/messages/description/non-english.md b/packages/moderation/data/messages/description/non-english.md index 06ba85141..07d83a7da 100644 --- a/packages/moderation/data/messages/description/non-english.md +++ b/packages/moderation/data/messages/description/non-english.md @@ -1,5 +1,5 @@ ## No English Description -Per section 2.2 of %RULES% a project's [Summary](%PROJECT_SETTINGS_LINK%) and %PROJECT_DESCRIPTION_FLINK% must be in English, unless meant exclusively for non-English use, such as translations. +Per section 2.2 of %RULES%, a project's [Summary](%PROJECT_SETTINGS_LINK%) and %PROJECT_DESCRIPTION_FLINK% must be in English, unless meant exclusively for non-English use, such as translations. You may include your non-English Description if you would like but we ask that you also add an English translation of the Description to your project page, if you would like to use an online translator to do this, we recommend [DeepL](https://www.deepl.com/translator). diff --git a/packages/moderation/data/messages/description/non-standard-text.md b/packages/moderation/data/messages/description/non-standard-text.md index be648f276..e7aad9896 100644 --- a/packages/moderation/data/messages/description/non-standard-text.md +++ b/packages/moderation/data/messages/description/non-standard-text.md @@ -1,6 +1,6 @@ ## Description Accessibility -Per section 2 of %RULES% your description must be plainly readable and accessible. +Per section 2 of %RULES%, your description must be plainly readable and accessible. Using non-standard text characters like Zalgo or "fancy text" in place of text anywhere in your project, including the Description, Summary, or Title can make your project pages inaccessible. diff --git a/packages/moderation/data/messages/gallery/not-relevant.md b/packages/moderation/data/messages/gallery/not-relevant.md index 78f879669..49986ebb6 100644 --- a/packages/moderation/data/messages/gallery/not-relevant.md +++ b/packages/moderation/data/messages/gallery/not-relevant.md @@ -1,3 +1,3 @@ ## Unrelated Gallery Images -Per section 5.5 of %RULES% any images in your project's Gallery must be relevant to the project and also include a Title. +Per section 5.5 of %RULES%, any images in your project's Gallery must be relevant to the project and also include a Title. diff --git a/packages/moderation/data/messages/license/invalid_link.md b/packages/moderation/data/messages/license/invalid_link.md index dec1b9771..080d4deae 100644 --- a/packages/moderation/data/messages/license/invalid_link.md +++ b/packages/moderation/data/messages/license/invalid_link.md @@ -1,4 +1,4 @@ ## Invalid License Link -It's important that your project's License link is accurate and leads directly to a valid license for this content. -Your current link: `%PROJECT_LICENSE_URL%` does not appear to lead to a valid license for this project, or it is not publicly accessable. +It's important that your project's %PROJECT_LICENSE_FLINK% link is accurate and leads directly to a valid license for this content. +Your current link: `%PROJECT_LICENSE_URL%` does not appear to lead to a valid license for this project, or it is not publicly accessible. diff --git a/packages/moderation/data/messages/license/no_source-fork.md b/packages/moderation/data/messages/license/no_source-fork.md index 1ff659c73..ded248ea3 100644 --- a/packages/moderation/data/messages/license/no_source-fork.md +++ b/packages/moderation/data/messages/license/no_source-fork.md @@ -1,5 +1,5 @@ ## No Source Code Provided -Your project's license of `%PROJECT_LICENSE_NAME%`, requires source disclosure. +Your project's %PROJECT_LICENSE_FLINK% of `%PROJECT_LICENSE_NAME%`, requires source disclosure. Consider adding a Source link to your project's repository, or including a Sources file for each version as an Additional File. Keep in mind this may be a requirement of the source work's licensing, which must be abided per section 4 of %RULES%. diff --git a/packages/moderation/data/messages/license/no_source.md b/packages/moderation/data/messages/license/no_source.md index 76e7c7a9f..106efae08 100644 --- a/packages/moderation/data/messages/license/no_source.md +++ b/packages/moderation/data/messages/license/no_source.md @@ -1,4 +1,4 @@ ## No Source Code Provided -Your project's license of `%PROJECT_LICENSE_NAME%`, requires source disclosure. +Your project's %PROJECT_LICENSE_FLINK% of `%PROJECT_LICENSE_NAME%`, requires source disclosure. Consider adding a Source link to your project's repository, or including a Sources file for each version as an Additional File. You may also want to refer to %LICENSING_GUIDE% if you wish to select a different License, remember to make sure your selected License is consistent with the license in your project's files as well. diff --git a/packages/moderation/data/messages/links/misused.md b/packages/moderation/data/messages/links/misused.md index 15582bee4..22fe93ed6 100644 --- a/packages/moderation/data/messages/links/misused.md +++ b/packages/moderation/data/messages/links/misused.md @@ -1,4 +1,4 @@ ## Misuse of Links -Per section 5.4 of %RULES% all %PROJECT_LINKS_FLINK% must lead to correctly labeled publicly available resources that are directly related to your project. +Per section 5.4 of %RULES%, all %PROJECT_LINKS_FLINK% must lead to correctly labeled publicly available resources that are directly related to your project. Currently it looks like your %MISUSED_LINKS% link(s) are misused or incorrectly labeled. diff --git a/packages/moderation/data/messages/links/not_accessible.md b/packages/moderation/data/messages/links/not_accessible.md index 50f868bad..47b60f5c3 100644 --- a/packages/moderation/data/messages/links/not_accessible.md +++ b/packages/moderation/data/messages/links/not_accessible.md @@ -1,3 +1,3 @@ ## Unreachable Links -Per section 5.4 of %RULES% all %PROJECT_LINKS_FLINK% must lead to correctly labeled publicly available resources that are directly related to your project. +Per section 5.4 of %RULES%, all %PROJECT_LINKS_FLINK% must lead to correctly labeled publicly available resources that are directly related to your project. diff --git a/packages/moderation/data/messages/reupload/reupload.md b/packages/moderation/data/messages/reupload/reupload.md index 51fcab855..6c2cc9b7f 100644 --- a/packages/moderation/data/messages/reupload/reupload.md +++ b/packages/moderation/data/messages/reupload/reupload.md @@ -1,5 +1,5 @@ ## Reuploads are forbidden This project appears to contain content from %ORIGINAL_PROJECT% by %ORIGINAL_AUTHOR%. -Per section 4 of %RULES% this is strictly forbidden. +Per section 4 of %RULES%, this is strictly forbidden. If you believe this is an error, or you can verify you are the creator and rightful owner of this content please let us know. Otherwise, we ask that you **do not resubmit this project**. diff --git a/packages/moderation/data/messages/status-alerts/account_issues.md b/packages/moderation/data/messages/status-alerts/account_issues.md index 9c4fdc277..067e36695 100644 --- a/packages/moderation/data/messages/status-alerts/account_issues.md +++ b/packages/moderation/data/messages/status-alerts/account_issues.md @@ -1,5 +1,3 @@ ---- - ## Account Issues Indicated We're sorry to hear you're having trouble accessing your accounts, unfortunately, our moderation team is unable to assist with account-related issues. diff --git a/packages/moderation/data/messages/status-alerts/automod_confusion.md b/packages/moderation/data/messages/status-alerts/automod_confusion.md index 842f5b544..9acdaee0d 100644 --- a/packages/moderation/data/messages/status-alerts/automod_confusion.md +++ b/packages/moderation/data/messages/status-alerts/automod_confusion.md @@ -1,4 +1,4 @@ ---- +## Warnings from AutoMod Unfortunately, our AutoMod cannot read your project's Description or your messages to moderation. AutoMod will warn both you and our Moderation Staff about potential issues, but if you've already followed the necessary steps these warnings can safely be ignored. diff --git a/packages/moderation/data/messages/status-alerts/fixed.md b/packages/moderation/data/messages/status-alerts/fixed.md index 433588624..1300fd7be 100644 --- a/packages/moderation/data/messages/status-alerts/fixed.md +++ b/packages/moderation/data/messages/status-alerts/fixed.md @@ -1,5 +1,4 @@ ---- - ## Corrections Applied -I've gone ahead and corrected the issues listed above so your project can be Approved. +Your submission contained some issues which may have prevented your project from being published. +These have been corrected by our Moderation Team so your project can be Approved, be sure to read and understand each issue listed below to ensure a smooth review for your next submission. diff --git a/packages/moderation/data/messages/status-alerts/private.md b/packages/moderation/data/messages/status-alerts/private.md index cb9cd608d..ed82add51 100644 --- a/packages/moderation/data/messages/status-alerts/private.md +++ b/packages/moderation/data/messages/status-alerts/private.md @@ -1,8 +1,6 @@ ---- - ## Private Use -Under normal circumstances, your project would be rejected due to the issues listed above. +Under normal circumstances, your project would be rejected due to the issues listed below. However, since your project is not intended for public use, these requirements will be waived and your project will be unlisted. This means it will remain accessible through a direct link without appearing in public search results, allowing you to share it privately. If you're okay with this, or submitted your project to be unlisted already, than no further action is necessary. If you would like to publish your project publicly, please address all moderation concerns before resubmitting this project. diff --git a/packages/moderation/data/messages/summary/formatting.md b/packages/moderation/data/messages/summary/formatting.md index 8b9704a12..f641e593f 100644 --- a/packages/moderation/data/messages/summary/formatting.md +++ b/packages/moderation/data/messages/summary/formatting.md @@ -1,6 +1,6 @@ -## Insufficient Summary +## Invalid Summary Formatting -Per section 5.3 of %RULES% your Summary can not include any extra formatting such as lists, or links. +Per section 5.3 of %RULES%, your Summary can not include any extra formatting such as lists, or links. Your project summary should provide a brief overview of your project that informs and entices users. diff --git a/packages/moderation/data/messages/summary/insufficient.md b/packages/moderation/data/messages/summary/insufficient.md index 2505b8baa..12e012ca2 100644 --- a/packages/moderation/data/messages/summary/insufficient.md +++ b/packages/moderation/data/messages/summary/insufficient.md @@ -1,5 +1,5 @@ ## Insufficient Summary -Per section 5.3 of %RULES% your project summary should provide a brief overview of your project that informs and entices users. +Per section 5.3 of %RULES%, your project summary should provide a brief overview of your project that informs and entices users. This is the first thing most people will see about your mod other than the Logo, so it's important it be accurate, reasonably detailed, and exciting. diff --git a/packages/moderation/data/messages/summary/non-english.md b/packages/moderation/data/messages/summary/non-english.md index 64059f4d5..94c680967 100644 --- a/packages/moderation/data/messages/summary/non-english.md +++ b/packages/moderation/data/messages/summary/non-english.md @@ -1,5 +1,5 @@ ## No English Summary -Per section 2.2 of %RULES% a project's Summary and Description must be in English, unless meant exclusively for non-English use, such as translations. +Per section 2.2 of %RULES%, a project's Summary and Description must be in English, unless meant exclusively for non-English use, such as translations. You may include your non-English Summary but we ask that you also add an English translation. diff --git a/packages/moderation/data/messages/summary/repeat-title.md b/packages/moderation/data/messages/summary/repeat-title.md index e67061385..e16fc8052 100644 --- a/packages/moderation/data/messages/summary/repeat-title.md +++ b/packages/moderation/data/messages/summary/repeat-title.md @@ -1,6 +1,6 @@ ## Insufficient Summary -Per section 5.3 of %RULES% your Summary can not be the same as your project's Title. +Per section 5.3 of %RULES%, your Summary can not be the same as your project's Title. Your project summary should provide a brief overview of your project that informs and entices users. diff --git a/packages/moderation/data/messages/versions/alternate_versions-additional.md b/packages/moderation/data/messages/versions/alternate_versions-additional.md index ad9023cda..fdb9e9103 100644 --- a/packages/moderation/data/messages/versions/alternate_versions-additional.md +++ b/packages/moderation/data/messages/versions/alternate_versions-additional.md @@ -1,5 +1,5 @@ ## Unsupported Project -Per section 5.7 of [Modrinth's Content Rules](https://modrinth.com/legal/rules), Modrinth does not support uploading multiple variations of your project as Additional files. +Per section 5.7 of %RULES%, Modrinth does not support uploading multiple variations of your project as Additional files. Having alternate versions of your content on the same project will hurt the functionality of the Modrinth App and other supported launchers as it would prevent users from updating your content, and may make it harder for your users to find the content they want. We ask that you upload each alternate version of your project as a new project, ensuring that all users will be able to access and easily find your content. diff --git a/packages/moderation/data/messages/versions/alternate_versions-server-additional.md b/packages/moderation/data/messages/versions/alternate_versions-server-additional.md index 7095cd848..51a9e2871 100644 --- a/packages/moderation/data/messages/versions/alternate_versions-server-additional.md +++ b/packages/moderation/data/messages/versions/alternate_versions-server-additional.md @@ -1,4 +1,4 @@ ## Incorrect Additional Files -Per section 5.7 of [Modrinth's Content Rules](https://modrinth.com/legal/rules) the additional files section should only be used for specific designated purposes such as a `Sources.jar`. +Per section 5.7 of %RULES%, the additional files section should only be used for specific designated purposes such as a `Sources.jar`. To ensure a smooth experience for you and your users, please upload each alternate version of your modpack as its own Modpack project, thank you. diff --git a/packages/moderation/data/messages/versions/alternate_versions-zip.md b/packages/moderation/data/messages/versions/alternate_versions-zip.md index 284ffa871..70fafd931 100644 --- a/packages/moderation/data/messages/versions/alternate_versions-zip.md +++ b/packages/moderation/data/messages/versions/alternate_versions-zip.md @@ -1,5 +1,5 @@ ## Incorrect Additional Files -Per section 5.7 of [Modrinth's Content Rules](https://modrinth.com/legal/rules) the additional files section should only be used for specific designated purposes such as a `Sources.jar`. +Per section 5.7 of %RULES%, the additional files section should only be used for specific designated purposes such as a `Sources.jar`. Modrinth does not support the upload of modpacks in the `.zip` format, as this may cause issues for Modrinth users or distribute copyrighted content without the proper permissions. If you would like to upload a server-specific version of your modpack, consider creating a separate Modpack project. diff --git a/packages/moderation/data/messages/versions/incorrect_additional_files.md b/packages/moderation/data/messages/versions/incorrect_additional_files.md index 475367e1b..6756d8d20 100644 --- a/packages/moderation/data/messages/versions/incorrect_additional_files.md +++ b/packages/moderation/data/messages/versions/incorrect_additional_files.md @@ -1,5 +1,5 @@ ## Incorrect Use of Additional Files -It looks like you've uploaded multiple primary files to one Version as Additional Files. Per section 5.7 of %RULES% each Version of your project must include only one primary file that corresponds to its respective Minecraft and loader versions. +It looks like you've uploaded multiple primary files to one Version as Additional Files. Per section 5.7 of %RULES%, each Version of your project must include only one primary file that corresponds to its respective Minecraft and loader versions. This allows users to easily find and download the content they need for their game profile with ease. The Additional Files feature can be used for things like a `Sources.jar`. Please upload each version of your project separately, thank you. diff --git a/packages/moderation/data/messages/versions/redist_libs.md b/packages/moderation/data/messages/versions/redist_libs.md index be6189801..ffb964637 100644 --- a/packages/moderation/data/messages/versions/redist_libs.md +++ b/packages/moderation/data/messages/versions/redist_libs.md @@ -1,4 +1,4 @@ -## Excessive File Size +## Unnecessary redistribution of dependencies This project appears to include libs or dependencies, unnecessarily redistributing their entire contents. This is often due to an error in project structure or compilation, and in some cases, may violate the copyrights or licensing agreements of these libraries. diff --git a/packages/moderation/data/stages/description.ts b/packages/moderation/data/stages/description.ts index beab75148..f68d142e6 100644 --- a/packages/moderation/data/stages/description.ts +++ b/packages/moderation/data/stages/description.ts @@ -94,6 +94,15 @@ const description: Stage = { message: async () => (await import('../messages/description/non-standard-text.md?raw')).default, } as ButtonAction, + { + id: 'description_clarity', + type: 'button', + label: 'Unclear / Misleading', + weight: 407, + suggestedStatus: 'rejected', + severity: 'high', + message: async () => (await import('../messages/description/clarity.md?raw')).default, + } as ButtonAction, ], } diff --git a/packages/moderation/data/stages/status-alerts.ts b/packages/moderation/data/stages/status-alerts.ts index 6c8dbc53f..7e0d77241 100644 --- a/packages/moderation/data/stages/status-alerts.ts +++ b/packages/moderation/data/stages/status-alerts.ts @@ -15,7 +15,7 @@ const statusAlerts: Stage = { id: 'status_corrections_applied', type: 'button', label: 'Corrections applied', - weight: 999999, + weight: -999999, suggestedStatus: 'approved', disablesActions: ['status_private_use', 'status_account_issues'], message: async () => (await import('../messages/status-alerts/fixed.md?raw')).default, @@ -24,7 +24,7 @@ const statusAlerts: Stage = { id: 'status_private_use', type: 'button', label: 'Private use', - weight: 999999, + weight: -999999, suggestedStatus: 'flagged', disablesActions: ['status_corrections_applied', 'status_account_issues'], message: async () => (await import('../messages/status-alerts/private.md?raw')).default, @@ -33,7 +33,7 @@ const statusAlerts: Stage = { id: 'status_account_issues', type: 'button', label: 'Account issues', - weight: 999999, + weight: -999999, suggestedStatus: 'rejected', disablesActions: ['status_corrections_applied', 'status_private_use'], message: async () => @@ -78,7 +78,7 @@ const statusAlerts: Stage = { id: 'status_automod_confusion', type: 'button', label: `Automod confusion`, - weight: 999999, + weight: -999999, message: async () => (await import('../messages/status-alerts/automod_confusion.md?raw')).default, } as ButtonAction, diff --git a/packages/moderation/data/stages/title-slug.ts b/packages/moderation/data/stages/title-slug.ts index 4fe699a69..55d32a62c 100644 --- a/packages/moderation/data/stages/title-slug.ts +++ b/packages/moderation/data/stages/title-slug.ts @@ -1,10 +1,28 @@ import { BookOpenIcon } from '@modrinth/assets' import type { Stage } from '../../types/stage' +import type { Project } from '@modrinth/utils' + +function hasCustomSlug(project: Project): boolean { + return ( + project.slug !== + project.title + .trim() + .toLowerCase() + .replaceAll(' ', '-') + .replaceAll(/[^a-zA-Z0-9!@$()`.+,_"-]/g, '') + .replaceAll(/--+/gm, '-') + ) +} const titleSlug: Stage = { title: 'Are the Name and URL accurate and appropriate?', id: 'title-&-slug', - text: async () => (await import('../messages/checklist-text/title-slug.md?raw')).default, + text: async (project) => { + let text = (await import('../messages/checklist-text/title-slug/title.md?raw')).default + if (hasCustomSlug(project)) + text += (await import('../messages/checklist-text/title-slug/slug.md?raw')).default + return text + }, icon: BookOpenIcon, guidance_url: 'https://modrinth.com/legal/rules#miscellaneous', actions: [ @@ -63,6 +81,7 @@ const titleSlug: Stage = { label: 'Slug issues?', suggestedStatus: 'rejected', severity: 'low', + shouldShow: (project) => hasCustomSlug(project), options: [ { label: 'Misused', diff --git a/packages/moderation/data/stages/versions.ts b/packages/moderation/data/stages/versions.ts index 7f5ca33a0..bf8e31963 100644 --- a/packages/moderation/data/stages/versions.ts +++ b/packages/moderation/data/stages/versions.ts @@ -135,11 +135,11 @@ const versions: Stage = { { id: 'versions_redist_libs', type: 'button', - label: 'Oversized File', + label: 'Packed Libs', suggestedStatus: `rejected`, severity: `medium`, weight: 1003, - shouldShow: (project) => project.project_type === 'mod', + shouldShow: (project) => project.project_type === 'mod' || project.project_type === 'plugin', message: async () => (await import('../messages/versions/redist_libs.md?raw')).default, } as ButtonAction, { diff --git a/packages/moderation/utils.ts b/packages/moderation/utils.ts index 9aafa0588..9feb8c272 100644 --- a/packages/moderation/utils.ts +++ b/packages/moderation/utils.ts @@ -259,7 +259,7 @@ export function flattenProjectVariables(project: Project): Record Date: Fri, 1 Aug 2025 21:24:40 +0100 Subject: [PATCH 5/8] fix: approve status incorrect (#4104) --- .../ui/moderation/checklist/ModerationChecklist.vue | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue b/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue index d456c5b8b..0bb5c7362 100644 --- a/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue +++ b/apps/frontend/src/components/ui/moderation/checklist/ModerationChecklist.vue @@ -259,7 +259,7 @@ - @@ -355,6 +355,7 @@ import { renderHighlightedString, type ModerationJudgements, type ModerationModpackItem, + type ProjectStatus, } from "@modrinth/utils"; import { computedAsync, useLocalStorage } from "@vueuse/core"; import { @@ -527,7 +528,7 @@ function handleKeybinds(event: KeyboardEvent) { tryResetProgress: resetProgress, tryExitModeration: () => emit("exit"), - tryApprove: () => sendMessage("approved"), + tryApprove: () => sendMessage(props.project.requested_status), tryReject: () => sendMessage("rejected"), tryWithhold: () => sendMessage("withheld"), tryEditMessage: goBackToStages, @@ -1208,7 +1209,7 @@ function generateModpackMessage(allFiles: { } const hasNextProject = ref(false); -async function sendMessage(status: "approved" | "rejected" | "withheld") { +async function sendMessage(status: ProjectStatus) { try { await useBaseFetch(`project/${props.project.id}`, { method: "PATCH", From b33e12c71de776b3af3970547202ccb61f63b9cf Mon Sep 17 00:00:00 2001 From: IMB11 Date: Fri, 1 Aug 2025 22:22:22 +0100 Subject: [PATCH 6/8] fix: startup settings not visible on hard page refresh/direct load (#4100) * fix: startup settings not visible on hard page refresh/direct load * refactor: const func => named --- .../servers/manage/[id]/options/startup.vue | 53 +++++++------------ 1 file changed, 18 insertions(+), 35 deletions(-) diff --git a/apps/frontend/src/pages/servers/manage/[id]/options/startup.vue b/apps/frontend/src/pages/servers/manage/[id]/options/startup.vue index bd9a7edd4..7080f0e1c 100644 --- a/apps/frontend/src/pages/servers/manage/[id]/options/startup.vue +++ b/apps/frontend/src/pages/servers/manage/[id]/options/startup.vue @@ -42,7 +42,7 @@