diff --git a/apps/frontend/.env. b/apps/frontend/.env. new file mode 100644 index 0000000000..29aad1d10a --- /dev/null +++ b/apps/frontend/.env. @@ -0,0 +1,4 @@ +BASE_URL=http://127.0.0.1:8000/v2/ +BROWSER_BASE_URL=http://127.0.0.1:8000/v2/ +PYRO_BASE_URL=https://staging-archon.modrinth.com +PROD_OVERRIDE=true diff --git a/apps/frontend/src/composables/featureFlags.ts b/apps/frontend/src/composables/featureFlags.ts index a1acb5878c..89e1a6151c 100644 --- a/apps/frontend/src/composables/featureFlags.ts +++ b/apps/frontend/src/composables/featureFlags.ts @@ -46,6 +46,7 @@ export const DEFAULT_FEATURE_FLAGS = validateValues({ showDiscoverProjectButtons: false, useV1ContentTabAPI: true, labrinthApiCanary: false, + dismissedExternalProjectsInfo: false, } as const) export type FeatureFlag = keyof typeof DEFAULT_FEATURE_FLAGS diff --git a/apps/frontend/src/layouts/default.vue b/apps/frontend/src/layouts/default.vue index 6ef59f08c5..5a0776a265 100644 --- a/apps/frontend/src/layouts/default.vue +++ b/apps/frontend/src/layouts/default.vue @@ -323,6 +323,11 @@ color: 'orange', link: '/moderation/reports', }, + { + id: 'external-projects', + color: 'orange', + link: '/moderation/external-projects', + }, { divider: true, }, @@ -377,6 +382,9 @@ + @@ -705,6 +713,7 @@ import { DropdownIcon, FileIcon, GlassesIcon, + GlobeIcon, HamburgerIcon, HomeIcon, IssuesIcon, @@ -877,6 +886,10 @@ const messages = defineMessages({ id: 'layout.action.reports', defaultMessage: 'Review reports', }, + externalProjects: { + id: 'layout.action.external-projects', + defaultMessage: 'External projects', + }, lookupByEmail: { id: 'layout.action.lookup-by-email', defaultMessage: 'Lookup by email', diff --git a/apps/frontend/src/locales/en-US/index.json b/apps/frontend/src/locales/en-US/index.json index 6fbe35c465..c5f4c96e36 100644 --- a/apps/frontend/src/locales/en-US/index.json +++ b/apps/frontend/src/locales/en-US/index.json @@ -1748,9 +1748,54 @@ "layout.nav.upgrade-to-modrinth-plus": { "message": "Upgrade to Modrinth+" }, + "moderation.external-projects.empty-description": { + "message": "Type at least 3 characters of a project’s title to begin browsing." + }, + "moderation.external-projects.empty-flame-id-description": { + "message": "Type the numeric project ID, then use lookup for an exact match." + }, + "moderation.external-projects.empty-flame-id-title": { + "message": "Enter a CurseForge project ID" + }, + "moderation.external-projects.empty-sha1-description": { + "message": "Paste the full 40-character hex hash, then use lookup for an exact match." + }, + "moderation.external-projects.empty-sha1-title": { + "message": "Enter a SHA-1 hash" + }, + "moderation.external-projects.empty-title": { + "message": "Enter a search term to get started" + }, + "moderation.external-projects.lookup-curseforge-id": { + "message": "Lookup CurseForge ID" + }, + "moderation.external-projects.lookup-sha1-hash": { + "message": "Lookup SHA-1" + }, + "moderation.external-projects.no-results-by-flame-id": { + "message": "No external project has that CurseForge ID" + }, + "moderation.external-projects.no-results-by-sha1": { + "message": "No external file has that SHA-1 hash" + }, + "moderation.external-projects.no-results-by-title": { + "message": "No projects matched that title search" + }, + "moderation.external-projects.page-title": { + "message": "External projects - Modrinth" + }, + "moderation.external-projects.search-by-title": { + "message": "Search by title" + }, + "moderation.external-projects.search-placeholder": { + "message": "Search external projects..." + }, "moderation.moderate": { "message": "Moderate" }, + "moderation.page.external-projects": { + "message": "External projects" + }, "moderation.page.projects": { "message": "Projects" }, @@ -1758,7 +1803,7 @@ "message": "Reports" }, "moderation.page.technicalReview": { - "message": "Technical Review" + "message": "Tech review" }, "muralpay.account-type.checking": { "message": "Checking" diff --git a/apps/frontend/src/pages/[type]/[id]/settings.vue b/apps/frontend/src/pages/[type]/[id]/settings.vue index 9b51e4bb8d..ccb5283955 100644 --- a/apps/frontend/src/pages/[type]/[id]/settings.vue +++ b/apps/frontend/src/pages/[type]/[id]/settings.vue @@ -8,6 +8,7 @@ import { InfoIcon, LinkIcon, ServerIcon, + SignatureIcon, TagsIcon, UsersIcon, VersionIcon, @@ -46,6 +47,10 @@ const navItems = computed(() => { projectV3.value?.project_types?.some((type) => ['mod', 'modpack'].includes(type)) && isStaff(currentMember.value?.user) + const hasPermissionsPage = computed(() => + projectV3.value?.project_types?.some((type) => ['modpack'].includes(type)), + ) + const items = [ { link: `/${base}/settings`, @@ -75,6 +80,11 @@ const navItems = computed(() => { label: formatMessage(commonProjectSettingsMessages.description), icon: AlignLeftIcon, }, + hasPermissionsPage.value && { + link: `/${base}/settings/permissions`, + label: formatMessage(commonProjectSettingsMessages.permissions), + icon: SignatureIcon, + }, !isServerProject.value && { link: `/${base}/settings/versions`, label: formatMessage(commonProjectSettingsMessages.versions), diff --git a/apps/frontend/src/pages/[type]/[id]/settings/permissions.vue b/apps/frontend/src/pages/[type]/[id]/settings/permissions.vue new file mode 100644 index 0000000000..3588672aff --- /dev/null +++ b/apps/frontend/src/pages/[type]/[id]/settings/permissions.vue @@ -0,0 +1,173 @@ + + diff --git a/apps/frontend/src/pages/[type]/[id]/settings/versions.vue b/apps/frontend/src/pages/[type]/[id]/settings/versions.vue index 9f79d39e41..623352b3b3 100644 --- a/apps/frontend/src/pages/[type]/[id]/settings/versions.vue +++ b/apps/frontend/src/pages/[type]/[id]/settings/versions.vue @@ -15,6 +15,37 @@ @proceed="deleteVersion()" /> + + + ['4.0.0']) + +const messages = defineMessages({ + withheldVersionsWarningTitle: { + id: 'project.versions.withheld-versions-warning.title', + defaultMessage: + '{count, plural, one {Version {version_name}} other {Versions}} withheld due to unknown embedded content', + }, + withheldVersionsWarningDescription: { + id: 'project.versions.withheld-versions-warning.description', + defaultMessage: + '{count, plural, one {This version is} other {These versions are}} currently withheld and not publicly listed. Please provide proof that you have permission to redistribute certain files included in the modpack {count, plural, one {version} other {versions}}.', + }, + withheldVersionsWarningResolve: { + id: 'project.versions.withheld-versions-warning.resolve-button', + defaultMessage: 'Resolve', + }, +}) diff --git a/apps/frontend/src/pages/moderation.vue b/apps/frontend/src/pages/moderation.vue index 0fc5b74688..a90a205701 100644 --- a/apps/frontend/src/pages/moderation.vue +++ b/apps/frontend/src/pages/moderation.vue @@ -17,7 +17,7 @@ diff --git a/apps/labrinth/.sqlx/query-10e2a3b31ba94b93ed2d6c9753a5aabf13190a0b336089e6521022069813cf17.json b/apps/labrinth/.sqlx/query-10e2a3b31ba94b93ed2d6c9753a5aabf13190a0b336089e6521022069813cf17.json index ed3215a695..53cf350301 100644 --- a/apps/labrinth/.sqlx/query-10e2a3b31ba94b93ed2d6c9753a5aabf13190a0b336089e6521022069813cf17.json +++ b/apps/labrinth/.sqlx/query-10e2a3b31ba94b93ed2d6c9753a5aabf13190a0b336089e6521022069813cf17.json @@ -29,8 +29,7 @@ "low", "medium", "high", - "severe", - "malware" + "severe" ] } } @@ -46,7 +45,7 @@ false, true, false, - true + false ] }, "hash": "10e2a3b31ba94b93ed2d6c9753a5aabf13190a0b336089e6521022069813cf17" diff --git a/apps/labrinth/.sqlx/query-263ad3654f544ffb6061c839d49dada47fb382a76fdcabad2077fb1ef6d1010a.json b/apps/labrinth/.sqlx/query-263ad3654f544ffb6061c839d49dada47fb382a76fdcabad2077fb1ef6d1010a.json index a854453595..23c13cd169 100644 --- a/apps/labrinth/.sqlx/query-263ad3654f544ffb6061c839d49dada47fb382a76fdcabad2077fb1ef6d1010a.json +++ b/apps/labrinth/.sqlx/query-263ad3654f544ffb6061c839d49dada47fb382a76fdcabad2077fb1ef6d1010a.json @@ -44,8 +44,7 @@ "low", "medium", "high", - "severe", - "malware" + "severe" ] } } @@ -80,7 +79,7 @@ true, false, false, - true, + false, null ] }, diff --git a/apps/labrinth/.sqlx/query-56428d0eec87c0cdaca1183c642f0478b9974de6b6d95f7ca48de605b3bf1103.json b/apps/labrinth/.sqlx/query-56428d0eec87c0cdaca1183c642f0478b9974de6b6d95f7ca48de605b3bf1103.json new file mode 100644 index 0000000000..2a6d0ac4ce --- /dev/null +++ b/apps/labrinth/.sqlx/query-56428d0eec87c0cdaca1183c642f0478b9974de6b6d95f7ca48de605b3bf1103.json @@ -0,0 +1,21 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO moderation_external_licenses (id, title, status, link, proof, flame_project_id, inserted_at, inserted_by, updated_at, updated_by)\n SELECT * FROM UNNEST ($1::bigint[], $2::varchar[], $3::varchar[], $4::varchar[], $5::varchar[], $6::integer[], $7::timestamptz[], $8::bigint[], $7::timestamptz[], $8::bigint[])\n ON CONFLICT (id) DO UPDATE SET\n title = EXCLUDED.title,\n status = EXCLUDED.status,\n link = EXCLUDED.link,\n proof = EXCLUDED.proof,\n flame_project_id = EXCLUDED.flame_project_id,\n updated_at = EXCLUDED.updated_at,\n updated_by = EXCLUDED.updated_by\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Int8Array", + "VarcharArray", + "VarcharArray", + "VarcharArray", + "VarcharArray", + "Int4Array", + "TimestamptzArray", + "Int8Array" + ] + }, + "nullable": [] + }, + "hash": "56428d0eec87c0cdaca1183c642f0478b9974de6b6d95f7ca48de605b3bf1103" +} diff --git a/apps/labrinth/.sqlx/query-6542c79dffa73e462c527f1bd4ba67e658814d7a788259dc4b3874c54cb5ae57.json b/apps/labrinth/.sqlx/query-6542c79dffa73e462c527f1bd4ba67e658814d7a788259dc4b3874c54cb5ae57.json new file mode 100644 index 0000000000..8668834ed4 --- /dev/null +++ b/apps/labrinth/.sqlx/query-6542c79dffa73e462c527f1bd4ba67e658814d7a788259dc4b3874c54cb5ae57.json @@ -0,0 +1,83 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n mel.id,\n mel.title,\n mel.status,\n mel.link,\n mel.exceptions,\n mel.proof,\n mel.flame_project_id,\n mel.inserted_at,\n mel.inserted_by,\n mel.updated_at,\n mel.updated_by\n FROM moderation_external_licenses mel\n WHERE ($1::text IS NULL OR mel.title ILIKE '%' || $1 || '%')\n AND ($2::integer IS NULL OR mel.flame_project_id = $2)\n ORDER BY mel.id\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "status", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "link", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "exceptions", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "proof", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "flame_project_id", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "inserted_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "inserted_by", + "type_info": "Int8" + }, + { + "ordinal": 9, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "updated_by", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Text", + "Int4" + ] + }, + "nullable": [ + false, + true, + false, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "hash": "6542c79dffa73e462c527f1bd4ba67e658814d7a788259dc4b3874c54cb5ae57" +} diff --git a/apps/labrinth/.sqlx/query-7720108c0a9e93119f5252e2102eeea0ee67b228924e288d1d6c3e169e941688.json b/apps/labrinth/.sqlx/query-7720108c0a9e93119f5252e2102eeea0ee67b228924e288d1d6c3e169e941688.json new file mode 100644 index 0000000000..816a68f801 --- /dev/null +++ b/apps/labrinth/.sqlx/query-7720108c0a9e93119f5252e2102eeea0ee67b228924e288d1d6c3e169e941688.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n mef.external_license_id,\n mef.sha1,\n mef.filename\n FROM moderation_external_files mef\n WHERE mef.external_license_id = ANY($1)\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "external_license_id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "sha1", + "type_info": "Bytea" + }, + { + "ordinal": 2, + "name": "filename", + "type_info": "Text" + } + ], + "parameters": { + "Left": [ + "Int8Array" + ] + }, + "nullable": [ + false, + false, + true + ] + }, + "hash": "7720108c0a9e93119f5252e2102eeea0ee67b228924e288d1d6c3e169e941688" +} diff --git a/apps/labrinth/.sqlx/query-9369f0659c5fbd08463923a9b2bba49f4963315fd7667c6db96e6153e54a2fd2.json b/apps/labrinth/.sqlx/query-9369f0659c5fbd08463923a9b2bba49f4963315fd7667c6db96e6153e54a2fd2.json index 419c0ff25c..8ca4b69491 100644 --- a/apps/labrinth/.sqlx/query-9369f0659c5fbd08463923a9b2bba49f4963315fd7667c6db96e6153e54a2fd2.json +++ b/apps/labrinth/.sqlx/query-9369f0659c5fbd08463923a9b2bba49f4963315fd7667c6db96e6153e54a2fd2.json @@ -25,8 +25,7 @@ "low", "medium", "high", - "severe", - "malware" + "severe" ] } } diff --git a/apps/labrinth/.sqlx/query-99749414f92886a904158484661cae8928f78206c1cdf8adb66fde999bbe94d4.json b/apps/labrinth/.sqlx/query-99749414f92886a904158484661cae8928f78206c1cdf8adb66fde999bbe94d4.json new file mode 100644 index 0000000000..890112c0a6 --- /dev/null +++ b/apps/labrinth/.sqlx/query-99749414f92886a904158484661cae8928f78206c1cdf8adb66fde999bbe94d4.json @@ -0,0 +1,82 @@ +{ + "db_name": "PostgreSQL", + "query": "\n SELECT\n mel.id,\n mel.title,\n mel.status,\n mel.link,\n mel.exceptions,\n mel.proof,\n mel.flame_project_id,\n mel.inserted_at,\n mel.inserted_by,\n mel.updated_at,\n mel.updated_by\n FROM moderation_external_files mef\n INNER JOIN moderation_external_licenses mel ON mel.id = mef.external_license_id\n WHERE mef.sha1 = $1\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "status", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "link", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "exceptions", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "proof", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "flame_project_id", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "inserted_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "inserted_by", + "type_info": "Int8" + }, + { + "ordinal": 9, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "updated_by", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Bytea" + ] + }, + "nullable": [ + false, + true, + false, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "hash": "99749414f92886a904158484661cae8928f78206c1cdf8adb66fde999bbe94d4" +} diff --git a/apps/labrinth/.sqlx/query-b539eccb9fbb13270748f5c102dc0eb3325a39daa45f8964704713fb704a3e26.json b/apps/labrinth/.sqlx/query-b539eccb9fbb13270748f5c102dc0eb3325a39daa45f8964704713fb704a3e26.json new file mode 100644 index 0000000000..102c385b3f --- /dev/null +++ b/apps/labrinth/.sqlx/query-b539eccb9fbb13270748f5c102dc0eb3325a39daa45f8964704713fb704a3e26.json @@ -0,0 +1,90 @@ +{ + "db_name": "PostgreSQL", + "query": "\n UPDATE moderation_external_licenses\n SET title = COALESCE($2, title),\n status = $3,\n link = COALESCE($4, link),\n exceptions = COALESCE($5, exceptions),\n proof = COALESCE($6, proof),\n flame_project_id = COALESCE($7, flame_project_id),\n updated_at = $8,\n updated_by = $9\n WHERE id = $1\n RETURNING id, title, status, link, exceptions, proof, flame_project_id,\n inserted_at, inserted_by, updated_at, updated_by\n ", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "id", + "type_info": "Int8" + }, + { + "ordinal": 1, + "name": "title", + "type_info": "Text" + }, + { + "ordinal": 2, + "name": "status", + "type_info": "Text" + }, + { + "ordinal": 3, + "name": "link", + "type_info": "Text" + }, + { + "ordinal": 4, + "name": "exceptions", + "type_info": "Text" + }, + { + "ordinal": 5, + "name": "proof", + "type_info": "Text" + }, + { + "ordinal": 6, + "name": "flame_project_id", + "type_info": "Int4" + }, + { + "ordinal": 7, + "name": "inserted_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 8, + "name": "inserted_by", + "type_info": "Int8" + }, + { + "ordinal": 9, + "name": "updated_at", + "type_info": "Timestamptz" + }, + { + "ordinal": 10, + "name": "updated_by", + "type_info": "Int8" + } + ], + "parameters": { + "Left": [ + "Int8", + "Text", + "Text", + "Text", + "Text", + "Text", + "Int4", + "Timestamptz", + "Int8" + ] + }, + "nullable": [ + false, + true, + false, + true, + true, + true, + true, + true, + true, + true, + true + ] + }, + "hash": "b539eccb9fbb13270748f5c102dc0eb3325a39daa45f8964704713fb704a3e26" +} diff --git a/apps/labrinth/.sqlx/query-f2054ae7dcc89b21ed6b2f04526de1e7cddd68ac956143bef994104280a8dc07.json b/apps/labrinth/.sqlx/query-f2054ae7dcc89b21ed6b2f04526de1e7cddd68ac956143bef994104280a8dc07.json index c20c8ecdab..8cbe94abd5 100644 --- a/apps/labrinth/.sqlx/query-f2054ae7dcc89b21ed6b2f04526de1e7cddd68ac956143bef994104280a8dc07.json +++ b/apps/labrinth/.sqlx/query-f2054ae7dcc89b21ed6b2f04526de1e7cddd68ac956143bef994104280a8dc07.json @@ -22,8 +22,7 @@ "low", "medium", "high", - "severe", - "malware" + "severe" ] } } diff --git a/apps/labrinth/.sqlx/query-f26e41a619a51d5b5a39af6117b7d2f6106ec67a209a285b0a523a677dba4a5b.json b/apps/labrinth/.sqlx/query-f26e41a619a51d5b5a39af6117b7d2f6106ec67a209a285b0a523a677dba4a5b.json new file mode 100644 index 0000000000..8fe2ff889c --- /dev/null +++ b/apps/labrinth/.sqlx/query-f26e41a619a51d5b5a39af6117b7d2f6106ec67a209a285b0a523a677dba4a5b.json @@ -0,0 +1,18 @@ +{ + "db_name": "PostgreSQL", + "query": "\n INSERT INTO moderation_external_files (sha1, filename, external_license_id, inserted_at, inserted_by, updated_at, updated_by)\n SELECT * FROM UNNEST ($1::bytea[], $2::varchar[], $3::bigint[], $4::timestamptz[], $5::bigint[], $4::timestamptz[], $5::bigint[])\n ON CONFLICT (sha1) DO UPDATE SET\n filename = COALESCE(EXCLUDED.filename, moderation_external_files.filename),\n external_license_id = EXCLUDED.external_license_id,\n updated_at = EXCLUDED.updated_at,\n updated_by = EXCLUDED.updated_by\n ", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "ByteaArray", + "VarcharArray", + "Int8Array", + "TimestamptzArray", + "Int8Array" + ] + }, + "nullable": [] + }, + "hash": "f26e41a619a51d5b5a39af6117b7d2f6106ec67a209a285b0a523a677dba4a5b" +} diff --git a/apps/labrinth/.sqlx/query-f297b517bc3bbd8628c0c222c0e3daf8f4efbe628ee2e8ddbbb4b9734cc9c915.json b/apps/labrinth/.sqlx/query-f297b517bc3bbd8628c0c222c0e3daf8f4efbe628ee2e8ddbbb4b9734cc9c915.json deleted file mode 100644 index dc923578a9..0000000000 --- a/apps/labrinth/.sqlx/query-f297b517bc3bbd8628c0c222c0e3daf8f4efbe628ee2e8ddbbb4b9734cc9c915.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "db_name": "PostgreSQL", - "query": "\n INSERT INTO moderation_external_files (sha1, external_license_id)\n SELECT * FROM UNNEST ($1::bytea[], $2::bigint[])\n ON CONFLICT (sha1) DO NOTHING\n ", - "describe": { - "columns": [], - "parameters": { - "Left": [ - "ByteaArray", - "Int8Array" - ] - }, - "nullable": [] - }, - "hash": "f297b517bc3bbd8628c0c222c0e3daf8f4efbe628ee2e8ddbbb4b9734cc9c915" -} diff --git a/apps/labrinth/AGENTS.md b/apps/labrinth/AGENTS.md new file mode 100644 index 0000000000..0b73458d53 --- /dev/null +++ b/apps/labrinth/AGENTS.md @@ -0,0 +1,34 @@ +# Labrinth + +Labrinth is the backend API service for Modrinth, written in Rust. + +## Code style + +- When writing `sqlx` queries, NEVER use `query` directly. Always prefer using the `query!`, `query_as!`, `query_scalar!` macros. + +## Pre-PR Checks + +When the user refers to "perform[ing] pre-PR checks", do the following: + +- Run `cargo clippy -p labrinth --all-targets` — there must be ZERO warnings, otherwise CI will fail +- DO NOT run tests unless explicitly requested (they take a long time) +- Prepare the sqlx cache: cd into `apps/labrinth` and run `cargo sqlx prepare -- --tests` + - NEVER run `cargo sqlx prepare --workspace` + +## Testing + +- Run `cargo test -p labrinth --all-targets` to test your changes — all tests must pass + +## Local Services + +- Read the root `docker-compose.yml` to see what running services are available while developing +- Use `docker exec` to access these services + +### Clickhouse + +- Access: `docker exec labrinth-clickhouse clickhouse-client` +- Database: `staging_ariadne` + +### Postgres + +- Access: `docker exec labrinth-postgres psql -U labrinth -d labrinth -c ""` diff --git a/apps/labrinth/CLAUDE.md b/apps/labrinth/CLAUDE.md index fe4b705308..8d770e2555 100644 --- a/apps/labrinth/CLAUDE.md +++ b/apps/labrinth/CLAUDE.md @@ -1,30 +1 @@ -# Labrinth - -Labrinth is the backend API service for Modrinth, written in Rust. - -## Pre-PR Checks - -When the user refers to "perform[ing] pre-PR checks", do the following: - -- Run `cargo clippy -p labrinth --all-targets` — there must be ZERO warnings, otherwise CI will fail -- DO NOT run tests unless explicitly requested (they take a long time) -- Prepare the sqlx cache: cd into `apps/labrinth` and run `cargo sqlx prepare -- --tests` - - NEVER run `cargo sqlx prepare --workspace` - -## Testing - -- Run `cargo test -p labrinth --all-targets` to test your changes — all tests must pass - -## Local Services - -- Read the root `docker-compose.yml` to see what running services are available while developing -- Use `docker exec` to access these services - -### Clickhouse - -- Access: `docker exec labrinth-clickhouse clickhouse-client` -- Database: `staging_ariadne` - -### Postgres - -- Access: `docker exec labrinth-postgres psql -U labrinth -d labrinth -c ""` +Read @AGENTS.md diff --git a/apps/labrinth/fixtures/moderation-data.sql b/apps/labrinth/fixtures/moderation-data.sql new file mode 100644 index 0000000000..318f2fa043 --- /dev/null +++ b/apps/labrinth/fixtures/moderation-data.sql @@ -0,0 +1,18 @@ +-- Dummy moderation_external_licenses (explicit IDs required) +INSERT INTO moderation_external_licenses (id, title, status, link, exceptions, proof, flame_project_id, inserted_at, inserted_by, updated_at, updated_by) +VALUES + (9001, 'Example Mod', 'yes', 'https://example.com/license', NULL, 'Verified by team', 101, now(), 0, now(), 0), + (9002, 'Cool Resource Pack', 'no', 'https://coolpack.com/terms', 'Non-commercial only', 'DMCA takedown filed', 202, now(), 0, now(), 0), + (9003, 'Mystery Project', 'unidentified', NULL, NULL, NULL, NULL, now(), 0, now(), 0), + (9004, 'Widget Lib', 'with-attribution', 'https://widgets.dev/MIT', NULL, 'License header in JAR', 303, now(), 0, now(), 0), + (9005, 'Shadow Mod', 'permanent-no', 'https://shadow.net/eula', 'Redistribution restricted','Under review', NULL, now(), 0, now(), 0); + +-- Dummy moderation_external_files (sha1 stored as ASCII bytes of hex string, matching Rust's .as_bytes()) +INSERT INTO moderation_external_files (sha1, filename, external_license_id) +VALUES + ('aabbccdd11223344aabbccdd11223344aabbccdd', 'example-mod-1.0.jar', 9001), + ('11223344aabbccdd11223344aabbccdd11223344', 'example-mod-1.1.jar', 9001), + ('deadbeefdeadbeefdeadbeefdeadbeefdeadbeef', 'coolpack-v2.zip', 9002), + ('cafebabecafebabecafebabecafebabecafebabe', 'mystery.dat', 9003), + ('0102030405060708090a0b0c0d0e0f1011121314', 'widget-lib.jar', 9004); +-- License 9005 intentionally has no files (tests empty linked_files case) diff --git a/apps/labrinth/migrations/20260406134638_moderation_external_audit_columns.sql b/apps/labrinth/migrations/20260406134638_moderation_external_audit_columns.sql new file mode 100644 index 0000000000..7cef380a67 --- /dev/null +++ b/apps/labrinth/migrations/20260406134638_moderation_external_audit_columns.sql @@ -0,0 +1,12 @@ +ALTER TABLE moderation_external_licenses + ADD COLUMN inserted_at timestamptz, + ADD COLUMN inserted_by bigint REFERENCES users(id), + ADD COLUMN updated_at timestamptz, + ADD COLUMN updated_by bigint REFERENCES users(id); + +ALTER TABLE moderation_external_files + ADD COLUMN filename text, + ADD COLUMN inserted_at timestamptz, + ADD COLUMN inserted_by bigint REFERENCES users(id), + ADD COLUMN updated_at timestamptz, + ADD COLUMN updated_by bigint REFERENCES users(id); diff --git a/apps/labrinth/src/database/models/mod.rs b/apps/labrinth/src/database/models/mod.rs index 8945c4bb81..0db87c5082 100644 --- a/apps/labrinth/src/database/models/mod.rs +++ b/apps/labrinth/src/database/models/mod.rs @@ -11,6 +11,7 @@ pub mod ids; pub mod image_item; pub mod legacy_loader_fields; pub mod loader_fields; +pub mod moderation_external_item; pub mod moderation_lock_item; pub mod notification_item; pub mod notifications_deliveries_item; diff --git a/apps/labrinth/src/database/models/moderation_external_item.rs b/apps/labrinth/src/database/models/moderation_external_item.rs new file mode 100644 index 0000000000..ea5120c75c --- /dev/null +++ b/apps/labrinth/src/database/models/moderation_external_item.rs @@ -0,0 +1,99 @@ +use chrono::{DateTime, Utc}; + +use crate::database::models::DBUserId; + +pub struct ExternalLicense { + pub id: i64, + pub title: Option, + pub status: String, + pub link: Option, + pub proof: Option, + pub flame_project_id: Option, +} + +impl ExternalLicense { + pub async fn insert_many( + exec: impl sqlx::PgExecutor<'_>, + licenses: &[ExternalLicense], + user_id: DBUserId, + ) -> sqlx::Result<()> { + let now = Utc::now(); + + let ids: Vec = licenses.iter().map(|x| x.id).collect(); + let titles: Vec> = + licenses.iter().map(|x| x.title.clone()).collect(); + let statuses: Vec = + licenses.iter().map(|x| x.status.clone()).collect(); + let links: Vec> = + licenses.iter().map(|x| x.link.clone()).collect(); + let proofs: Vec> = + licenses.iter().map(|x| x.proof.clone()).collect(); + let flame_ids: Vec> = + licenses.iter().map(|x| x.flame_project_id).collect(); + let nows: Vec> = vec![now; licenses.len()]; + let user_ids: Vec = vec![user_id.0; licenses.len()]; + + sqlx::query!( + r#" + INSERT INTO moderation_external_licenses (id, title, status, link, proof, flame_project_id, inserted_at, inserted_by, updated_at, updated_by) + SELECT * FROM UNNEST ($1::bigint[], $2::varchar[], $3::varchar[], $4::varchar[], $5::varchar[], $6::integer[], $7::timestamptz[], $8::bigint[], $7::timestamptz[], $8::bigint[]) + ON CONFLICT (id) DO UPDATE SET + title = EXCLUDED.title, + status = EXCLUDED.status, + link = EXCLUDED.link, + proof = EXCLUDED.proof, + flame_project_id = EXCLUDED.flame_project_id, + updated_at = EXCLUDED.updated_at, + updated_by = EXCLUDED.updated_by + "#, + &ids, + &titles as _, + &statuses, + &links as _, + &proofs as _, + &flame_ids as _, + &nows, + &user_ids, + ) + .execute(exec) + .await?; + + Ok(()) + } + + pub async fn insert_files( + exec: impl sqlx::PgExecutor<'_>, + hashes: &[Vec], + filenames: &[Option], + license_ids: &[i64], + user_id: DBUserId, + ) -> sqlx::Result<()> { + let now = Utc::now(); + let nows: Vec> = vec![now; license_ids.len()]; + let user_ids: Vec = vec![user_id.0; license_ids.len()]; + + let filenames: Vec> = + filenames.iter().cloned().collect(); + + sqlx::query!( + r#" + INSERT INTO moderation_external_files (sha1, filename, external_license_id, inserted_at, inserted_by, updated_at, updated_by) + SELECT * FROM UNNEST ($1::bytea[], $2::varchar[], $3::bigint[], $4::timestamptz[], $5::bigint[], $4::timestamptz[], $5::bigint[]) + ON CONFLICT (sha1) DO UPDATE SET + filename = COALESCE(EXCLUDED.filename, moderation_external_files.filename), + external_license_id = EXCLUDED.external_license_id, + updated_at = EXCLUDED.updated_at, + updated_by = EXCLUDED.updated_by + "#, + hashes, + &filenames as _, + license_ids, + &nows, + &user_ids, + ) + .execute(exec) + .await?; + + Ok(()) + } +} diff --git a/apps/labrinth/src/queue/moderation.rs b/apps/labrinth/src/queue/moderation.rs index 4ff4b69e21..7d852f4eb3 100644 --- a/apps/labrinth/src/queue/moderation.rs +++ b/apps/labrinth/src/queue/moderation.rs @@ -1,6 +1,7 @@ use crate::auth::checks::filter_visible_versions; use crate::database; use crate::database::PgPool; +use crate::database::models::DBUserId; use crate::database::models::notification_item::NotificationBuilder; use crate::database::models::thread_item::ThreadMessageBuilder; use crate::database::redis::RedisPool; @@ -507,6 +508,7 @@ impl AutomatedModerationQueue { .fetch_all(&pool).await?; let mut insert_hashes = Vec::new(); + let mut insert_filenames = Vec::new(); let mut insert_ids = Vec::new(); for row in rows { @@ -518,6 +520,7 @@ impl AutomatedModerationQueue { }); insert_hashes.push(hash.clone().as_bytes().to_vec()); + insert_filenames.push(Some(file_name.clone())); insert_ids.push(row.id); hashes.remove(index); @@ -526,16 +529,13 @@ impl AutomatedModerationQueue { } if !insert_ids.is_empty() && !insert_hashes.is_empty() { - sqlx::query!( - " - INSERT INTO moderation_external_files (sha1, external_license_id) - SELECT * FROM UNNEST ($1::bytea[], $2::bigint[]) - ON CONFLICT (sha1) DO NOTHING - ", - &insert_hashes[..], - &insert_ids[..] + crate::database::models::moderation_external_item::ExternalLicense::insert_files( + &pool, + &insert_hashes, + &insert_filenames, + &insert_ids, + DBUserId(0), ) - .execute(&pool) .await?; } diff --git a/apps/labrinth/src/routes/internal/moderation/external_license.rs b/apps/labrinth/src/routes/internal/moderation/external_license.rs new file mode 100644 index 0000000000..cbcf03b245 --- /dev/null +++ b/apps/labrinth/src/routes/internal/moderation/external_license.rs @@ -0,0 +1,334 @@ +use std::collections::HashMap; + +use actix_web::{HttpRequest, get, patch, post, web}; +use chrono::{DateTime, Utc}; +use serde::{Deserialize, Serialize}; + +use crate::database::PgPool; +use crate::database::redis::RedisPool; +use crate::models::pats::Scopes; +use crate::queue::moderation::ApprovalType; +use crate::routes::ApiError; +use crate::{auth::check_is_moderator_from_headers, queue::session::AuthQueue}; + +pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) { + cfg.service(search) + .service(get_by_sha1) + .service(update_license); +} + +#[derive(Serialize, Deserialize, utoipa::ToSchema)] +pub struct ExternalProject { + pub id: i64, + pub title: Option, + pub status: ApprovalType, + pub link: Option, + pub exceptions: Option, + pub proof: Option, + pub flame_project_id: Option, + pub inserted_at: Option>, + pub inserted_by: Option, + pub updated_at: Option>, + pub updated_by: Option, + pub linked_files: Vec, +} + +#[derive(Serialize, Deserialize, Clone, utoipa::ToSchema)] +pub struct LinkedFile { + pub name: Option, + pub sha1: String, +} + +#[derive(Deserialize, utoipa::ToSchema)] +pub struct SearchRequest { + pub title: Option, + pub flame_id: Option, +} + +#[derive(Deserialize, utoipa::ToSchema)] +pub struct UpdateLicenseRequest { + pub title: Option, + pub status: ApprovalType, + pub link: Option, + pub exceptions: Option, + pub proof: Option, + pub flame_project_id: Option, +} + +struct LicenseRow { + id: i64, + title: Option, + status: String, + link: Option, + exceptions: Option, + proof: Option, + flame_project_id: Option, + inserted_at: Option>, + inserted_by: Option, + updated_at: Option>, + updated_by: Option, +} + +impl LicenseRow { + fn into_external_project( + self, + linked_files: Vec, + ) -> ExternalProject { + ExternalProject { + id: self.id, + title: self.title, + status: ApprovalType::from_string(&self.status) + .unwrap_or(ApprovalType::Unidentified), + link: self.link, + exceptions: self.exceptions, + proof: self.proof, + flame_project_id: self.flame_project_id, + inserted_at: self.inserted_at, + inserted_by: self.inserted_by, + updated_at: self.updated_at, + updated_by: self.updated_by, + linked_files, + } + } +} + +async fn fetch_linked_files( + pool: &PgPool, + license_ids: &[i64], +) -> Result>, ApiError> { + if license_ids.is_empty() { + return Ok(HashMap::new()); + } + + let file_rows = sqlx::query!( + r#" + SELECT + mef.external_license_id, + mef.sha1, + mef.filename + FROM moderation_external_files mef + WHERE mef.external_license_id = ANY($1) + "#, + license_ids, + ) + .fetch_all(pool) + .await?; + + let mut map: HashMap> = HashMap::new(); + for row in file_rows { + map.entry(row.external_license_id) + .or_default() + .push(LinkedFile { + name: row.filename, + sha1: hex::encode(&row.sha1), + }); + } + Ok(map) +} + +#[utoipa::path] +#[post("/search")] +async fn search( + req: HttpRequest, + pool: web::Data, + redis: web::Data, + session_queue: web::Data, + body: web::Json, +) -> Result>, ApiError> { + check_is_moderator_from_headers( + &req, + &**pool, + &redis, + &session_queue, + Scopes::PROJECT_READ, + ) + .await?; + + let rows = sqlx::query!( + r#" + SELECT + mel.id, + mel.title, + mel.status, + mel.link, + mel.exceptions, + mel.proof, + mel.flame_project_id, + mel.inserted_at, + mel.inserted_by, + mel.updated_at, + mel.updated_by + FROM moderation_external_licenses mel + WHERE ($1::text IS NULL OR mel.title ILIKE '%' || $1 || '%') + AND ($2::integer IS NULL OR mel.flame_project_id = $2) + ORDER BY mel.id + "#, + body.title, + body.flame_id, + ) + .fetch_all(&**pool) + .await?; + + let license_ids: Vec = rows.iter().map(|r| r.id).collect(); + let files_map = fetch_linked_files(&pool, &license_ids).await?; + + let results = rows + .into_iter() + .map(|row| { + let linked_files = + files_map.get(&row.id).cloned().unwrap_or_default(); + LicenseRow { + id: row.id, + title: row.title, + status: row.status, + link: row.link, + exceptions: row.exceptions, + proof: row.proof, + flame_project_id: row.flame_project_id, + inserted_at: row.inserted_at, + inserted_by: row.inserted_by, + updated_at: row.updated_at, + updated_by: row.updated_by, + } + .into_external_project(linked_files) + }) + .collect(); + + Ok(web::Json(results)) +} + +#[utoipa::path] +#[get("/by-sha1/{sha1}")] +async fn get_by_sha1( + req: HttpRequest, + pool: web::Data, + redis: web::Data, + session_queue: web::Data, + path: web::Path<(String,)>, +) -> Result, ApiError> { + check_is_moderator_from_headers( + &req, + &**pool, + &redis, + &session_queue, + Scopes::PROJECT_READ, + ) + .await?; + + let sha1 = path.into_inner().0; + + let row = sqlx::query!( + r#" + SELECT + mel.id, + mel.title, + mel.status, + mel.link, + mel.exceptions, + mel.proof, + mel.flame_project_id, + mel.inserted_at, + mel.inserted_by, + mel.updated_at, + mel.updated_by + FROM moderation_external_files mef + INNER JOIN moderation_external_licenses mel ON mel.id = mef.external_license_id + WHERE mef.sha1 = $1 + "#, + sha1.as_bytes().to_vec(), + ) + .fetch_optional(&**pool) + .await? + .ok_or(ApiError::NotFound)?; + + let files_map = fetch_linked_files(&pool, &[row.id]).await?; + let linked_files = files_map.get(&row.id).cloned().unwrap_or_default(); + + Ok(web::Json( + LicenseRow { + id: row.id, + title: row.title, + status: row.status, + link: row.link, + exceptions: row.exceptions, + proof: row.proof, + flame_project_id: row.flame_project_id, + inserted_at: row.inserted_at, + inserted_by: row.inserted_by, + updated_at: row.updated_at, + updated_by: row.updated_by, + } + .into_external_project(linked_files), + )) +} + +#[utoipa::path] +#[patch("/{id}")] +async fn update_license( + req: HttpRequest, + pool: web::Data, + redis: web::Data, + session_queue: web::Data, + path: web::Path<(i64,)>, + body: web::Json, +) -> Result, ApiError> { + let user = check_is_moderator_from_headers( + &req, + &**pool, + &redis, + &session_queue, + Scopes::PROJECT_READ, + ) + .await?; + + let id = path.into_inner().0; + + let result = sqlx::query!( + r#" + UPDATE moderation_external_licenses + SET title = COALESCE($2, title), + status = $3, + link = COALESCE($4, link), + exceptions = COALESCE($5, exceptions), + proof = COALESCE($6, proof), + flame_project_id = COALESCE($7, flame_project_id), + updated_at = $8, + updated_by = $9 + WHERE id = $1 + RETURNING id, title, status, link, exceptions, proof, flame_project_id, + inserted_at, inserted_by, updated_at, updated_by + "#, + id, + body.title, + body.status.as_str(), + body.link, + body.exceptions, + body.proof, + body.flame_project_id, + Utc::now(), + user.id.0 as i64, + ) + .fetch_optional(&**pool) + .await? + .ok_or(ApiError::NotFound)?; + + let files_map = fetch_linked_files(&pool, &[id]).await?; + let linked_files = files_map.get(&id).cloned().unwrap_or_default(); + + Ok(web::Json( + LicenseRow { + id: result.id, + title: result.title, + status: result.status, + link: result.link, + exceptions: result.exceptions, + proof: result.proof, + flame_project_id: result.flame_project_id, + inserted_at: result.inserted_at, + inserted_by: result.inserted_by, + updated_at: result.updated_at, + updated_by: result.updated_by, + } + .into_external_project(linked_files), + )) +} diff --git a/apps/labrinth/src/routes/internal/moderation/mod.rs b/apps/labrinth/src/routes/internal/moderation/mod.rs index a4e9d656dc..efa4b998c3 100644 --- a/apps/labrinth/src/routes/internal/moderation/mod.rs +++ b/apps/labrinth/src/routes/internal/moderation/mod.rs @@ -3,6 +3,7 @@ use crate::auth::get_user_from_headers; use crate::database; use crate::database::PgPool; use crate::database::models::DBModerationLock; +use crate::database::models::moderation_external_item; use crate::database::redis::RedisPool; use crate::models::ids::OrganizationId; use crate::models::projects::{Project, ProjectStatus}; @@ -17,6 +18,7 @@ use ownership::get_projects_ownership; use serde::{Deserialize, Serialize}; use std::collections::HashMap; +mod external_license; mod ownership; mod tech_review; @@ -31,6 +33,10 @@ pub fn config(cfg: &mut utoipa_actix_web::service_config::ServiceConfig) { .service( utoipa_actix_web::scope("/tech-review") .configure(tech_review::config), + ) + .service( + utoipa_actix_web::scope("/external-license") + .configure(external_license::config), ); } @@ -397,7 +403,7 @@ async fn set_project_meta( session_queue: web::Data, judgements: web::Json>, ) -> Result<(), ApiError> { - check_is_moderator_from_headers( + let user = check_is_moderator_from_headers( &req, &**pool, &redis, @@ -408,14 +414,10 @@ async fn set_project_meta( let mut transaction = pool.begin().await?; - let mut ids = Vec::new(); - let mut titles = Vec::new(); - let mut statuses = Vec::new(); - let mut links = Vec::new(); - let mut proofs = Vec::new(); - let mut flame_ids = Vec::new(); - + let mut licenses = Vec::new(); let mut file_hashes = Vec::new(); + let mut file_filenames = Vec::new(); + let mut file_license_ids = Vec::new(); for (hash, judgement) in judgements.0 { let id = random_base62(8); @@ -441,41 +443,38 @@ async fn set_project_meta( } => (title, status, link, proof, None), }; - ids.push(id as i64); - titles.push(title); - statuses.push(status.as_str()); - links.push(link); - proofs.push(proof); - flame_ids.push(flame_id); + licenses.push(moderation_external_item::ExternalLicense { + id: id as i64, + title, + status: status.as_str().to_string(), + link, + proof, + flame_project_id: flame_id, + }); file_hashes.push(hash); + file_filenames.push(None); + file_license_ids.push(id as i64); } - sqlx::query( - " - INSERT INTO moderation_external_licenses (id, title, status, link, proof, flame_project_id) - SELECT * FROM UNNEST ($1::bigint[], $2::varchar[], $3::varchar[], $4::varchar[], $5::varchar[], $6::integer[]) - " + let user_id = database::models::ids::DBUserId::from(user.id); + + moderation_external_item::ExternalLicense::insert_many( + &mut transaction, + &licenses, + user_id, ) - .bind(&ids[..]) - .bind(&titles[..]) - .bind(&statuses[..]) - .bind(&links[..]) - .bind(&proofs[..]) - .bind(&flame_ids[..]) - .execute(&mut transaction) - .await?; + .await?; - sqlx::query( - " - INSERT INTO moderation_external_files (sha1, external_license_id) - SELECT * FROM UNNEST ($1::bytea[], $2::bigint[]) - ON CONFLICT (sha1) - DO NOTHING - ", + moderation_external_item::ExternalLicense::insert_files( + &mut transaction, + &file_hashes + .iter() + .map(|x| x.as_bytes().to_vec()) + .collect::>(), + &file_filenames, + &file_license_ids, + user_id, ) - .bind(&file_hashes[..]) - .bind(&ids[..]) - .execute(&mut transaction) .await?; transaction.commit().await?; diff --git a/docker-compose.yml b/docker-compose.yml index a2979181fd..f64fe828a3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -51,167 +51,6 @@ services: interval: 3s timeout: 5s retries: 3 - elasticsearch-certs: - image: elasticsearch:9.3.0 - container_name: labrinth-elasticsearch-certs - user: '0' - networks: - - elasticsearch-mesh - restart: 'no' - volumes: - - elasticsearch-certs:/usr/share/elasticsearch/config/certs - command: | - bash -c ' - set -euo pipefail - if [ ! -s config/certs/ca/ca.crt ] || [ ! -s config/certs/elasticsearch0/elasticsearch0.crt ] || [ ! -s config/certs/elasticsearch1/elasticsearch1.crt ] || [ ! -s config/certs/elasticsearch2/elasticsearch2.crt ]; then - rm -rf config/certs/* - printf "%s\n" \ - "instances:" \ - " - name: elasticsearch0" \ - " dns:" \ - " - elasticsearch0" \ - " - localhost" \ - " ip:" \ - " - 127.0.0.1" \ - " - name: elasticsearch1" \ - " dns:" \ - " - elasticsearch1" \ - " - localhost" \ - " ip:" \ - " - 127.0.0.1" \ - " - name: elasticsearch2" \ - " dns:" \ - " - elasticsearch2" \ - " - localhost" \ - " ip:" \ - " - 127.0.0.1" \ - > config/certs/instances.yml - bin/elasticsearch-certutil ca --silent --pem --out config/certs/ca.zip - unzip config/certs/ca.zip -d config/certs - bin/elasticsearch-certutil cert --silent --pem --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key --out config/certs/certs.zip - unzip config/certs/certs.zip -d config/certs - fi - chown -R 1000:0 config/certs - find config/certs -type d -exec chmod 750 {} \; - find config/certs -type f -exec chmod 640 {} \; - echo "Set up certificates" - ' - elasticsearch0: - image: elasticsearch:9.3.0 - container_name: labrinth-elasticsearch0 - networks: - - elasticsearch-mesh - restart: on-failure - depends_on: - elasticsearch-certs: - condition: service_completed_successfully - ports: - - '127.0.0.1:9200:9200' - volumes: - - elasticsearch0-data:/usr/share/elasticsearch/data - - elasticsearch-certs:/usr/share/elasticsearch/config/certs:ro - environment: - - logger.level=WARN - - node.name=elasticsearch0 - - cluster.name=labrinth - - cluster.initial_master_nodes=elasticsearch0,elasticsearch1,elasticsearch2 - - discovery.seed_hosts=elasticsearch1,elasticsearch2 - - bootstrap.memory_lock=false - # auth - - xpack.security.enabled=true - - xpack.security.transport.ssl.enabled=true - - xpack.security.transport.ssl.verification_mode=certificate - - xpack.security.transport.ssl.key=certs/elasticsearch0/elasticsearch0.key - - xpack.security.transport.ssl.certificate=certs/elasticsearch0/elasticsearch0.crt - - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt - - ELASTIC_USERNAME=elastic - - ELASTIC_PASSWORD=elastic - mem_limit: 1g - healthcheck: - test: - [ - 'CMD-SHELL', - 'curl -s -u elastic:elastic http://localhost:9200/_cluster/health | grep -qE "\"status\":\"(yellow|green)\""', - ] - interval: 10s - timeout: 5s - retries: 10 - elasticsearch1: - image: elasticsearch:9.3.0 - container_name: labrinth-elasticsearch1 - networks: - - elasticsearch-mesh - restart: on-failure - depends_on: - elasticsearch-certs: - condition: service_completed_successfully - volumes: - - elasticsearch1-data:/usr/share/elasticsearch/data - - elasticsearch-certs:/usr/share/elasticsearch/config/certs:ro - environment: - - logger.level=WARN - - node.name=elasticsearch1 - - cluster.name=labrinth - - cluster.initial_master_nodes=elasticsearch0,elasticsearch1,elasticsearch2 - - discovery.seed_hosts=elasticsearch0,elasticsearch2 - - bootstrap.memory_lock=false - # auth - - xpack.security.enabled=true - - xpack.security.transport.ssl.enabled=true - - xpack.security.transport.ssl.verification_mode=certificate - - xpack.security.transport.ssl.key=certs/elasticsearch1/elasticsearch1.key - - xpack.security.transport.ssl.certificate=certs/elasticsearch1/elasticsearch1.crt - - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt - - ELASTIC_USERNAME=elastic - - ELASTIC_PASSWORD=elastic - mem_limit: 1g - healthcheck: - test: - [ - 'CMD-SHELL', - 'curl -s -u elastic:elastic http://localhost:9200/_cluster/health | grep -qE "\"status\":\"(yellow|green)\""', - ] - interval: 10s - timeout: 5s - retries: 10 - elasticsearch2: - image: elasticsearch:9.3.0 - container_name: labrinth-elasticsearch2 - networks: - - elasticsearch-mesh - restart: on-failure - depends_on: - elasticsearch-certs: - condition: service_completed_successfully - volumes: - - elasticsearch2-data:/usr/share/elasticsearch/data - - elasticsearch-certs:/usr/share/elasticsearch/config/certs:ro - environment: - - logger.level=WARN - - node.name=elasticsearch2 - - cluster.name=labrinth - - cluster.initial_master_nodes=elasticsearch0,elasticsearch1,elasticsearch2 - - discovery.seed_hosts=elasticsearch0,elasticsearch1 - - bootstrap.memory_lock=false - # auth - - xpack.security.enabled=true - - xpack.security.transport.ssl.enabled=true - - xpack.security.transport.ssl.verification_mode=certificate - - xpack.security.transport.ssl.key=certs/elasticsearch2/elasticsearch2.key - - xpack.security.transport.ssl.certificate=certs/elasticsearch2/elasticsearch2.crt - - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt - - ELASTIC_USERNAME=elastic - - ELASTIC_PASSWORD=elastic - mem_limit: 1g - healthcheck: - test: - [ - 'CMD-SHELL', - 'curl -s -u elastic:elastic http://localhost:9200/_cluster/health | grep -qE "\"status\":\"(yellow|green)\""', - ] - interval: 10s - timeout: 5s - retries: 10 redis: image: redis:alpine container_name: labrinth-redis diff --git a/package.json b/package.json index 6baa3104f6..8401134738 100644 --- a/package.json +++ b/package.json @@ -42,7 +42,7 @@ "vue": "^3.5.13", "yaml": "^2.8.2" }, - "packageManager": "pnpm@9.15.0", + "packageManager": "pnpm@10.33.0", "pnpm": { "patchedDependencies": { "readable-stream@2.3.8": "patches/readable-stream@2.3.8.patch" diff --git a/packages/assets/generated-icons.ts b/packages/assets/generated-icons.ts index ff66853f3d..f6a88776bb 100644 --- a/packages/assets/generated-icons.ts +++ b/packages/assets/generated-icons.ts @@ -26,6 +26,7 @@ import _BadgeDollarSignIcon from './icons/badge-dollar-sign.svg?component' import _BanIcon from './icons/ban.svg?component' import _BellIcon from './icons/bell.svg?component' import _BellRingIcon from './icons/bell-ring.svg?component' +import _BinaryIcon from './icons/binary.svg?component' import _BlendIcon from './icons/blend.svg?component' import _BlocksIcon from './icons/blocks.svg?component' import _BoldIcon from './icons/bold.svg?component' @@ -209,6 +210,7 @@ import _ShieldIcon from './icons/shield.svg?component' import _ShieldAlertIcon from './icons/shield-alert.svg?component' import _ShieldCheckIcon from './icons/shield-check.svg?component' import _SignalIcon from './icons/signal.svg?component' +import _SignatureIcon from './icons/signature.svg?component' import _SkullIcon from './icons/skull.svg?component' import _SlashIcon from './icons/slash.svg?component' import _SortAscIcon from './icons/sort-asc.svg?component' @@ -413,6 +415,7 @@ export const BadgeDollarSignIcon = _BadgeDollarSignIcon export const BanIcon = _BanIcon export const BellIcon = _BellIcon export const BellRingIcon = _BellRingIcon +export const BinaryIcon = _BinaryIcon export const BlendIcon = _BlendIcon export const BlocksIcon = _BlocksIcon export const BoldIcon = _BoldIcon @@ -596,6 +599,7 @@ export const ShieldIcon = _ShieldIcon export const ShieldAlertIcon = _ShieldAlertIcon export const ShieldCheckIcon = _ShieldCheckIcon export const SignalIcon = _SignalIcon +export const SignatureIcon = _SignatureIcon export const SkullIcon = _SkullIcon export const SlashIcon = _SlashIcon export const SortAscIcon = _SortAscIcon diff --git a/packages/assets/icons/binary.svg b/packages/assets/icons/binary.svg new file mode 100644 index 0000000000..702973f520 --- /dev/null +++ b/packages/assets/icons/binary.svg @@ -0,0 +1,20 @@ + + + + + + + + + diff --git a/packages/assets/icons/signature.svg b/packages/assets/icons/signature.svg new file mode 100644 index 0000000000..298ef3587f --- /dev/null +++ b/packages/assets/icons/signature.svg @@ -0,0 +1,16 @@ + + + + + diff --git a/packages/tooling-config/package.json b/packages/tooling-config/package.json index ddfeaf52e7..4b8f998688 100644 --- a/packages/tooling-config/package.json +++ b/packages/tooling-config/package.json @@ -32,13 +32,16 @@ "typescript": ">=5.0.0" }, "devDependencies": { + "@eslint/compat": "^1.4.1", "@eslint/js": "^9.32.0", + "@nuxt/eslint-config": "^0.5.7", "@prettier/plugin-xml": "^3.4.2", "@vue/tsconfig": "^0.7.0", "eslint": "^9.32.0", "eslint-config-prettier": "^10.1.8", "eslint-plugin-prettier": "^5.5.3", "eslint-plugin-simple-import-sort": "^12.1.1", + "eslint-plugin-turbo": "^2.5.4", "eslint-plugin-vue": "^10.4.0", "vue-eslint-parser": "^10.1.3", "globals": "^16.3.0", diff --git a/packages/ui/src/components/base/Admonition.vue b/packages/ui/src/components/base/Admonition.vue index 90a3178b14..5094289fd0 100644 --- a/packages/ui/src/components/base/Admonition.vue +++ b/packages/ui/src/components/base/Admonition.vue @@ -27,7 +27,10 @@ {{ header }} -
+
{{ body }}
diff --git a/packages/ui/src/components/base/StyledInput.vue b/packages/ui/src/components/base/StyledInput.vue index 1d904571bd..355975fb1b 100644 --- a/packages/ui/src/components/base/StyledInput.vue +++ b/packages/ui/src/components/base/StyledInput.vue @@ -71,6 +71,9 @@ variant === 'outlined' ? 'bg-transparent border border-solid border-button-bg rounded-l-xl border-r-0' : 'bg-surface-4 border-none rounded-xl', + { + 'placeholder:text-sm': type === 'search', + }, ]" @input="onInput" @focus="isFocused = true" diff --git a/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue b/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue new file mode 100644 index 0000000000..724132b664 --- /dev/null +++ b/packages/ui/src/components/external_files/ExternalProjectLookupCard.vue @@ -0,0 +1,192 @@ + + + diff --git a/packages/ui/src/components/external_files/index.ts b/packages/ui/src/components/external_files/index.ts new file mode 100644 index 0000000000..e9cdbb8b8b --- /dev/null +++ b/packages/ui/src/components/external_files/index.ts @@ -0,0 +1,2 @@ +export { default as ExternalProjectLookupCard } from './ExternalProjectLookupCard.vue' +export type { ExternalLicenseStatus } from './types.ts' diff --git a/packages/ui/src/components/external_files/types.ts b/packages/ui/src/components/external_files/types.ts new file mode 100644 index 0000000000..331d41bf95 --- /dev/null +++ b/packages/ui/src/components/external_files/types.ts @@ -0,0 +1,7 @@ +export type ExternalLicenseStatus = + | 'yes' + | 'with-attribution-and-source' + | 'with-attribution' + | 'no' + | 'permanent-no' + | 'unidentified' diff --git a/packages/ui/src/components/index.ts b/packages/ui/src/components/index.ts index 1f00fa63a7..5726399250 100644 --- a/packages/ui/src/components/index.ts +++ b/packages/ui/src/components/index.ts @@ -5,6 +5,7 @@ export * from './brand' export * from './changelog' export * from './chart' export * from './content' +export * from './external_files' export * from './modal' export * from './nav' export * from './page' diff --git a/packages/ui/src/locales/en-US/index.json b/packages/ui/src/locales/en-US/index.json index 447fc9a42e..e66fc40518 100644 --- a/packages/ui/src/locales/en-US/index.json +++ b/packages/ui/src/locales/en-US/index.json @@ -440,6 +440,57 @@ "content.selection-bar.selected-count-simple": { "defaultMessage": "{count, number} selected" }, + "external-files.lookup-card.allowed-label": { + "defaultMessage": "Allowed:" + }, + "external-files.lookup-card.curseforge-project": { + "defaultMessage": "CurseForge project" + }, + "external-files.lookup-card.files-heading": { + "defaultMessage": "Files" + }, + "external-files.lookup-card.first-identified-name": { + "defaultMessage": "First identified name:" + }, + "external-files.lookup-card.last-edited": { + "defaultMessage": "Last edited on {date} by {user}" + }, + "external-files.lookup-card.no-files": { + "defaultMessage": "No files available for external project." + }, + "external-files.lookup-card.notes-label": { + "defaultMessage": "Notes:" + }, + "external-files.lookup-card.project-link": { + "defaultMessage": "Project link" + }, + "external-files.lookup-card.proof-label": { + "defaultMessage": "Proof:" + }, + "external-files.lookup-card.sha1-label": { + "defaultMessage": "SHA-1:" + }, + "external-files.lookup-card.status.no": { + "defaultMessage": "No" + }, + "external-files.lookup-card.status.permanent-no": { + "defaultMessage": "Permanent no" + }, + "external-files.lookup-card.status.unidentified": { + "defaultMessage": "Unidentified" + }, + "external-files.lookup-card.status.with-attribution": { + "defaultMessage": "With attribution" + }, + "external-files.lookup-card.status.with-attribution-and-source": { + "defaultMessage": "With attribution and source" + }, + "external-files.lookup-card.status.yes": { + "defaultMessage": "Yes" + }, + "external-files.lookup-card.unknown-file-name": { + "defaultMessage": "Unknown" + }, "files.conflict-modal.header": { "defaultMessage": "Extract summary" }, @@ -2393,6 +2444,9 @@ "project.settings.upload.title": { "defaultMessage": "Upload" }, + "project.settings.versions.permissions": { + "defaultMessage": "Permissions" + }, "project.settings.versions.title": { "defaultMessage": "Versions" }, diff --git a/packages/ui/src/utils/common-messages.ts b/packages/ui/src/utils/common-messages.ts index fe61d1e783..5c00a6ce61 100644 --- a/packages/ui/src/utils/common-messages.ts +++ b/packages/ui/src/utils/common-messages.ts @@ -949,6 +949,10 @@ export const commonProjectSettingsMessages = defineMessages({ id: 'project.settings.versions.title', defaultMessage: 'Versions', }, + permissions: { + id: 'project.settings.versions.permissions', + defaultMessage: 'Permissions', + }, view: { id: 'project.settings.view.title', defaultMessage: 'View', diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index acb12e2cc8..494d9717b8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -6,7 +6,7 @@ settings: patchedDependencies: readable-stream@2.3.8: - hash: h52dazg37p4h3yox67pw36akse + hash: 3045f7adf989b4e668a4a13819b7285b0de186b79bbf22408acaf2a41c6eaa86 path: patches/readable-stream@2.3.8.patch importers: @@ -164,7 +164,7 @@ importers: devDependencies: '@eslint/compat': specifier: ^1.1.1 - version: 1.4.1(eslint@9.39.2(jiti@2.6.1)) + version: 1.4.1(eslint@9.39.2(jiti@1.21.7)) '@formatjs/cli': specifier: ^6.2.12 version: 6.12.2(@vue/compiler-core@3.5.27)(vue@3.5.27(typescript@5.9.3)) @@ -173,22 +173,22 @@ importers: version: link:../../packages/tooling-config '@nuxt/eslint-config': specifier: ^0.5.6 - version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) '@taijased/vue-render-tracker': specifier: ^1.0.7 version: 1.0.7(vue@3.5.27(typescript@5.9.3)) '@vitejs/plugin-vue': specifier: ^6.0.3 - version: 6.0.4(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + version: 6.0.4(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) autoprefixer: specifier: ^10.4.19 version: 10.4.24(postcss@8.5.6) eslint: specifier: ^9.9.1 - version: 9.39.2(jiti@2.6.1) + version: 9.39.2(jiti@1.21.7) eslint-plugin-turbo: specifier: ^2.5.4 - version: 2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2) + version: 2.8.2(eslint@9.39.2(jiti@1.21.7))(turbo@2.8.2) postcss: specifier: ^8.4.39 version: 8.5.6 @@ -206,7 +206,7 @@ importers: version: 5.9.3 vite: specifier: ^8.0.0 - version: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + version: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue-component-type-helpers: specifier: ^3.1.8 version: 3.2.4 @@ -280,7 +280,7 @@ importers: version: 0.11.3(magicast@0.5.1)(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3))) '@sentry/nuxt': specifier: ^10.33.0 - version: 10.38.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(rollup@4.57.1)(vue@3.5.27(typescript@5.9.3)) + version: 10.38.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(rollup@4.57.1)(vue@3.5.27(typescript@5.9.3)) '@tanstack/vue-query': specifier: ^5.90.7 version: 5.92.9(vue@3.5.27(typescript@5.9.3)) @@ -289,7 +289,7 @@ importers: version: 0.172.0 '@vitejs/plugin-vue': specifier: ^6.0.3 - version: 6.0.4(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + version: 6.0.4(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) '@vue-email/components': specifier: ^0.0.21 version: 0.0.21(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)) @@ -407,7 +407,7 @@ importers: version: 10.5.0 nuxt: specifier: ^3.20.2 - version: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) + version: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) postcss: specifier: ^8.4.39 version: 8.5.6 @@ -553,9 +553,15 @@ importers: specifier: '>=5.0.0' version: 5.9.3 devDependencies: + '@eslint/compat': + specifier: ^1.4.1 + version: 1.4.1(eslint@9.39.2(jiti@2.6.1)) '@eslint/js': specifier: ^9.32.0 version: 9.39.2 + '@nuxt/eslint-config': + specifier: ^0.5.7 + version: 0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@prettier/plugin-xml': specifier: ^3.4.2 version: 3.4.2(prettier@3.8.1) @@ -574,6 +580,9 @@ importers: eslint-plugin-simple-import-sort: specifier: ^12.1.1 version: 12.1.1(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-turbo: + specifier: ^2.5.4 + version: 2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2) eslint-plugin-vue: specifier: ^10.4.0 version: 10.7.0(@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(vue-eslint-parser@10.2.0(eslint@9.39.2(jiti@2.6.1))) @@ -745,7 +754,7 @@ importers: version: 5.2.4(vite@5.4.21(@types/node@20.19.31)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0))(vue@3.5.27(typescript@5.9.3)) eslint-plugin-storybook: specifier: ^10.1.10 - version: 10.2.4(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) + version: 10.2.4(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3) storybook: specifier: ^10.1.10 version: 10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) @@ -2191,155 +2200,183 @@ packages: resolution: {integrity: sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm64@1.2.4': resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.0.5': resolution: {integrity: sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.0.4': resolution: {integrity: sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.0.4': resolution: {integrity: sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.0.4': resolution: {integrity: sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.0.4': resolution: {integrity: sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.33.5': resolution: {integrity: sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.33.5': resolution: {integrity: sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.33.5': resolution: {integrity: sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.33.5': resolution: {integrity: sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.33.5': resolution: {integrity: sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.33.5': resolution: {integrity: sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.33.5': resolution: {integrity: sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==} @@ -2869,48 +2906,56 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-arm64-musl@0.110.0': resolution: {integrity: sha512-53GjCVY8kvymk9P6qNDh6zyblcehF5QHstq9QgCjv13ONGRnSHjeds0PxIwiihD7h295bxsWs84DN39syLPH4Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-minify/binding-linux-ppc64-gnu@0.110.0': resolution: {integrity: sha512-li8XcN81dxbJDMBESnTgGhoiAQ+CNIdM0QGscZ4duVPjCry1RpX+5FJySFbGqG3pk4s9ZzlL/vtQtbRzZIZOzg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-riscv64-gnu@0.110.0': resolution: {integrity: sha512-SweKfsnLKShu6UFV8mwuj1d1wmlNoL/FlAxPUzwjEBgwiT2HQkY24KnjBH+TIA+//1O83kzmWKvvs4OuEhdIEQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-riscv64-musl@0.110.0': resolution: {integrity: sha512-oH8G4aFMP8XyTsEpdANC5PQyHgSeGlopHZuW1rpyYcaErg5YaK0vXjQ4EM5HVvPm+feBV24JjxgakTnZoF3aOQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-minify/binding-linux-s390x-gnu@0.110.0': resolution: {integrity: sha512-W9na+Vza7XVUlpf8wMt4QBfH35KeTENEmnpPUq3NSlbQHz8lSlSvhAafvo43NcKvHAXV3ckD/mUf2VkqSdbklg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-x64-gnu@0.110.0': resolution: {integrity: sha512-XJdA4mmmXOjJxSRgNJXsDP7Xe8h3gQhmb56hUcCrvq5d+h5UcEi2pR8rxsdIrS8QmkLuBA3eHkGK8E27D7DTgQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-minify/binding-linux-x64-musl@0.110.0': resolution: {integrity: sha512-QqzvALuOTtSckI8x467R4GNArzYDb/yEh6aNzLoeaY1O7vfT7SPDwlOEcchaTznutpeS9Dy8gUS/AfqtUHaufw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-minify/binding-openharmony-arm64@0.110.0': resolution: {integrity: sha512-gAMssLs2Q3+uhLZxanh1DF+27Kaug3cf4PXb9AB7XK81DR+LVcKySXaoGYoOs20Co0fFSphd6rRzKge2qDK3dA==} @@ -2988,48 +3033,56 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-arm64-musl@0.110.0': resolution: {integrity: sha512-5xwm1hPrGGvjCVtTWNGJ39MmQGnyipoIDShneGBgSrnDh0XX+COAO7AZKajgNipqgNq5rGEItpzFkMtSDyx0bQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-parser/binding-linux-ppc64-gnu@0.110.0': resolution: {integrity: sha512-I8Xop7z+enuvW1xe0AcRQ9XqFNkUYgeXusyGjCyW6TstRb62P90h+nL1AoGaUMy0E0518DJam5vRYVRgXaAzYg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-gnu@0.110.0': resolution: {integrity: sha512-XPM0jpght/AuHnweNaIo0twpId6rWFs8NrTkMijxcsRQMzNBeSQQgYm9ErrutmKQS6gb8XNAEIkYXHgPmhdDPg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-riscv64-musl@0.110.0': resolution: {integrity: sha512-ylJIuJyMzAqR191QeCwZLEkyo4Sx817TNILjNhT0W1EDQusGicOYKSsGXM/2DHCNYGcidV+MQ8pUVzNeVmuM6g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-parser/binding-linux-s390x-gnu@0.110.0': resolution: {integrity: sha512-DL6oR0PfYor9tBX9xlAxMUVwfm6+sKTL4H+KiQ6JKP3xkJTwBIdDCgeN2AjMht1D3N40uUwVq3v8/2fqnZRgLQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-x64-gnu@0.110.0': resolution: {integrity: sha512-+e6ws5JLpFehdK+wh6q8icx1iM3Ao+9dtItVWFcRiXxSvGcIlS9viWcMvXKrmcsyVDUf81dnvuMSBigNslxhIQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-parser/binding-linux-x64-musl@0.110.0': resolution: {integrity: sha512-6DiYhVdXKOzB01+j/tyrB6/d2o6b4XYFQvcbBRNbVHIimS6nl992y3V3mGG3NaA+uCZAzhT3M3btTdKAxE4A3A==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-parser/binding-openharmony-arm64@0.110.0': resolution: {integrity: sha512-U9KEK7tXdHrXl2eZpoHYGWj31ZSvdGiaXwjkJzeRN0elt89PXi+VcryRh6BAFbEz1EQpTteyMDwDXMgJVWM85A==} @@ -3113,48 +3166,56 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-arm64-musl@0.110.0': resolution: {integrity: sha512-e5JN94/oy+wevk76q+LMr+2klTTcO60uXa+Wkq558Ms7mdF2TvkKFI++d/JeiuIwJLTi/BxQ4qdT5FWcsHM/ug==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@oxc-transform/binding-linux-ppc64-gnu@0.110.0': resolution: {integrity: sha512-Y3/Tnnz1GvDpmv8FXBIKtdZPsdZklOEPdrL6NHrN5i2u54BOkybFaDSptgWF53wOrJlTrcmAVSE6fRKK9XCM2Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-riscv64-gnu@0.110.0': resolution: {integrity: sha512-Y0E35iA9/v9jlkNcP6tMJ+ZFOS0rLsWDqG6rU9z+X2R3fBFJBO9UARIK6ngx8upxk81y1TFR2CmBFhupfYdH6Q==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-riscv64-musl@0.110.0': resolution: {integrity: sha512-JOUSYFfHjBUs7xp2FHmZHb8eTYD/oEu0NklS6JgUauqnoXZHiTLPLVW2o2uVCqldnabYHcomuwI2iqVFYJNhTw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [riscv64] os: [linux] + libc: [musl] '@oxc-transform/binding-linux-s390x-gnu@0.110.0': resolution: {integrity: sha512-7blgoXF9D3Ngzb7eun23pNrHJpoV/TtE6LObwlZ3Nmb4oZ6Z+yMvBVaoW68NarbmvNGfZ95zrOjgm6cVETLYBA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-x64-gnu@0.110.0': resolution: {integrity: sha512-YQ2joGWCVDZVEU2cD/r/w49hVjDm/Qu1BvC/7zs8LvprzdLS/HyMXGF2oA0puw0b+AqgYaz3bhwKB2xexHyITQ==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@oxc-transform/binding-linux-x64-musl@0.110.0': resolution: {integrity: sha512-fkjr5qE632ULmNgvFXWDR/8668WxERz3tU7TQFp6JebPBneColitjSkdx6VKNVXEoMmQnOvBIGeP5tUNT384oA==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@oxc-transform/binding-openharmony-arm64@0.110.0': resolution: {integrity: sha512-HWH9Zj+lMrdSTqFRCZsvDWMz7OnMjbdGsm3xURXWfRZpuaz0bVvyuZNDQXc4FyyhRDsemICaJbU1bgeIpUJDGw==} @@ -3247,36 +3308,42 @@ packages: engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm-musl@2.5.6': resolution: {integrity: sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==} engines: {node: '>= 10.0.0'} cpu: [arm] os: [linux] + libc: [musl] '@parcel/watcher-linux-arm64-glibc@2.5.6': resolution: {integrity: sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-arm64-musl@2.5.6': resolution: {integrity: sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==} engines: {node: '>= 10.0.0'} cpu: [arm64] os: [linux] + libc: [musl] '@parcel/watcher-linux-x64-glibc@2.5.6': resolution: {integrity: sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [glibc] '@parcel/watcher-linux-x64-musl@2.5.6': resolution: {integrity: sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==} engines: {node: '>= 10.0.0'} cpu: [x64] os: [linux] + libc: [musl] '@parcel/watcher-wasm@2.5.6': resolution: {integrity: sha512-byAiBZ1t3tXQvc8dMD/eoyE7lTXYorhn+6uVW5AC+JGI1KtJC/LvDche5cfUE+qiefH+Ybq0bUCJU0aB1cSHUA==} @@ -3432,36 +3499,42 @@ packages: engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-arm64-musl@1.0.0-rc.12': resolution: {integrity: sha512-V6/wZztnBqlx5hJQqNWwFdxIKN0m38p8Jas+VoSfgH54HSj9tKTt1dZvG6JRHcjh6D7TvrJPWFGaY9UBVOaWPw==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [arm64] os: [linux] + libc: [musl] '@rolldown/binding-linux-ppc64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-AP3E9BpcUYliZCxa3w5Kwj9OtEVDYK6sVoUzy4vTOJsjPOgdaJZKFmN4oOlX0Wp0RPV2ETfmIra9x1xuayFB7g==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-s390x-gnu@1.0.0-rc.12': resolution: {integrity: sha512-nWwpvUSPkoFmZo0kQazZYOrT7J5DGOJ/+QHHzjvNlooDZED8oH82Yg67HvehPPLAg5fUff7TfWFHQS8IV1n3og==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [s390x] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-gnu@1.0.0-rc.12': resolution: {integrity: sha512-RNrafz5bcwRy+O9e6P8Z/OCAJW/A+qtBczIqVYwTs14pf4iV1/+eKEjdOUta93q2TsT/FI0XYDP3TCky38LMAg==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [glibc] '@rolldown/binding-linux-x64-musl@1.0.0-rc.12': resolution: {integrity: sha512-Jpw/0iwoKWx3LJ2rc1yjFrj+T7iHZn2JDg1Yny1ma0luviFS4mhAIcd1LFNxK3EYu3DHWCps0ydXQ5i/rrJ2ig==} engines: {node: ^20.19.0 || >=22.12.0} cpu: [x64] os: [linux] + libc: [musl] '@rolldown/binding-openharmony-arm64@1.0.0-rc.12': resolution: {integrity: sha512-vRugONE4yMfVn0+7lUKdKvN4D5YusEiPilaoO2sgUWpCvrncvWgPMzK00ZFFJuiPgLwgFNP5eSiUlv2tfc+lpA==} @@ -3598,66 +3671,79 @@ packages: resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.57.1': resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.57.1': resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.57.1': resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.57.1': resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.57.1': resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.57.1': resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.57.1': resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.57.1': resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.57.1': resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.57.1': resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.57.1': resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.57.1': resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.57.1': resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} @@ -4065,24 +4151,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.1.18': resolution: {integrity: sha512-1px92582HkPQlaaCkdRcio71p8bc8i/ap5807tPRDK/uw953cauQBT8c5tVGkOwrHMfc2Yh6UuxaH4vtTjGvHg==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.1.18': resolution: {integrity: sha512-v3gyT0ivkfBLoZGF9LyHmts0Isc8jHZyVcbzio6Wpzifg/+5ZJpDiRiUhDLkcr7f/r38SWNe7ucxmGW3j3Kb/g==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.1.18': resolution: {integrity: sha512-bhJ2y2OQNlcRwwgOAGMY0xTFStt4/wyU6pvI6LSuZpRgKQwxTec0/3Scu91O8ir7qCR3AuepQKLU/kX99FouqQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.1.18': resolution: {integrity: sha512-LffYTvPjODiP6PT16oNeUQJzNVyJl1cjIebq/rWWBF+3eDst5JGEFSc5cWxyRCJ0Mxl+KyIkqRxk1XPEs9x8TA==} @@ -4165,30 +4255,35 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-arm64-musl@2.5.0': resolution: {integrity: sha512-rQO1HhRUQqyEaal5dUVOQruTRda/TD36s9kv1hTxZiFuSq3558lsTjAcUEnMAtBcBkps20sbyTJNMT0AwYIk8Q==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@tauri-apps/cli-linux-riscv64-gnu@2.5.0': resolution: {integrity: sha512-7oS18FN46yDxyw1zX/AxhLAd7T3GrLj3Ai6s8hZKd9qFVzrAn36ESL7d3G05s8wEtsJf26qjXnVF4qleS3dYsA==} engines: {node: '>= 10'} cpu: [riscv64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-gnu@2.5.0': resolution: {integrity: sha512-SG5sFNL7VMmDBdIg3nO3EzNRT306HsiEQ0N90ILe3ZABYAVoPDO/ttpCO37ApLInTzrq/DLN+gOlC/mgZvLw1w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@tauri-apps/cli-linux-x64-musl@2.5.0': resolution: {integrity: sha512-QXDM8zp/6v05PNWju5ELsVwF0VH1n6b5pk2E6W/jFbbiwz80Vs1lACl9pv5kEHkrxBj+aWU/03JzGuIj2g3SkQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@tauri-apps/cli-win32-arm64-msvc@2.5.0': resolution: {integrity: sha512-pFSHFK6b+o9y4Un8w0gGLwVyFTZaC3P0kQ7umRt/BLDkzD5RnQ4vBM7CF8BCU5nkwmEBUCZd7Wt3TWZxe41o6Q==} @@ -4522,41 +4617,49 @@ packages: resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] + libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] + libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.11.1': resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] + libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.11.1': resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} @@ -6918,48 +7021,56 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-gnu@1.32.0: resolution: {integrity: sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.30.2: resolution: {integrity: sha512-5Vh9dGeblpTxWHpOx8iauV02popZDsCYMPIgiuw97OJ5uaDsL86cnqSFs5LZkG3ghHoX5isLgWzMs+eD1YzrnA==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-arm64-musl@1.32.0: resolution: {integrity: sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.30.2: resolution: {integrity: sha512-Cfd46gdmj1vQ+lR6VRTTadNHu6ALuw2pKR9lYq4FnhvgBc4zWY1EtZcAc6EffShbb1MFrIPfLDXD6Xprbnni4w==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-gnu@1.32.0: resolution: {integrity: sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.30.2: resolution: {integrity: sha512-XJaLUUFXb6/QG2lGIW6aIk6jKdtjtcffUT0NKvIqhSBY3hh9Ch+1LCeH80dR9q9LBjG3ewbDjnumefsLsP6aiA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-linux-x64-musl@1.32.0: resolution: {integrity: sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.30.2: resolution: {integrity: sha512-FZn+vaj7zLv//D/192WFFVA0RgHawIcHqLX9xuWiQt7P0PtdFEVaxgF9rjM/IRYHQXNnk61/H/gb2Ei+kUQ4xQ==} @@ -10974,6 +11085,12 @@ snapshots: '@eslint-community/regexpp@4.12.2': {} + '@eslint/compat@1.4.1(eslint@9.39.2(jiti@1.21.7))': + dependencies: + '@eslint/core': 0.17.0 + optionalDependencies: + eslint: 9.39.2(jiti@1.21.7) + '@eslint/compat@1.4.1(eslint@9.39.2(jiti@2.6.1))': dependencies: '@eslint/core': 0.17.0 @@ -11539,11 +11656,11 @@ snapshots: '@nuxt/devalue@2.0.2': {} - '@nuxt/devtools-kit@3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))': + '@nuxt/devtools-kit@3.1.1(magicast@0.5.1)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))': dependencies: '@nuxt/kit': 4.3.0(magicast@0.5.1) execa: 8.0.1 - vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) transitivePeerDependencies: - magicast @@ -11558,12 +11675,12 @@ snapshots: prompts: 2.4.2 semver: 7.7.3 - '@nuxt/devtools@3.1.1(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': + '@nuxt/devtools@3.1.1(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': dependencies: - '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + '@nuxt/devtools-kit': 3.1.1(magicast@0.5.1)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) '@nuxt/devtools-wizard': 3.1.1 '@nuxt/kit': 4.3.0(magicast@0.5.1) - '@vue/devtools-core': 8.0.5(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + '@vue/devtools-core': 8.0.5(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) '@vue/devtools-kit': 8.0.5 birpc: 2.9.0 consola: 3.4.2 @@ -11588,9 +11705,9 @@ snapshots: sirv: 3.0.2 structured-clone-es: 1.0.0 tinyglobby: 0.2.15 - vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) - vite-plugin-inspect: 11.3.3(@nuxt/kit@4.3.0(magicast@0.5.1))(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) - vite-plugin-vue-tracer: 1.2.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-plugin-inspect: 11.3.3(@nuxt/kit@4.3.0(magicast@0.5.1))(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite-plugin-vue-tracer: 1.2.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) which: 5.0.0 ws: 8.19.0 transitivePeerDependencies: @@ -11599,6 +11716,31 @@ snapshots: - utf-8-validate - vue + '@nuxt/eslint-config@0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@eslint/js': 9.39.2 + '@nuxt/eslint-plugin': 0.5.7(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint: 9.39.2(jiti@1.21.7) + eslint-config-flat-gitignore: 0.3.0(eslint@9.39.2(jiti@1.21.7)) + eslint-flat-config-utils: 0.4.0 + eslint-plugin-import-x: 4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)) + eslint-plugin-jsdoc: 50.8.0(eslint@9.39.2(jiti@1.21.7)) + eslint-plugin-regexp: 2.10.0(eslint@9.39.2(jiti@1.21.7)) + eslint-plugin-unicorn: 55.0.0(eslint@9.39.2(jiti@1.21.7)) + eslint-plugin-vue: 9.33.0(eslint@9.39.2(jiti@1.21.7)) + globals: 15.15.0 + local-pkg: 0.5.1 + pathe: 1.1.2 + vue-eslint-parser: 9.4.3(eslint@9.39.2(jiti@1.21.7)) + transitivePeerDependencies: + - '@typescript-eslint/utils' + - eslint-import-resolver-node + - supports-color + - typescript + '@nuxt/eslint-config@0.5.7(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint/js': 9.39.2 @@ -11624,6 +11766,15 @@ snapshots: - supports-color - typescript + '@nuxt/eslint-plugin@0.5.7(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint: 9.39.2(jiti@1.21.7) + transitivePeerDependencies: + - supports-color + - typescript + '@nuxt/eslint-plugin@0.5.7(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.54.0 @@ -11684,7 +11835,7 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxt/nitro-server@3.21.0(db0@0.3.4)(ioredis@5.9.2)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(rolldown@1.0.0-rc.12)(typescript@5.9.3)(xml2js@0.6.2)': + '@nuxt/nitro-server@3.21.0(db0@0.3.4)(ioredis@5.9.2)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(rolldown@1.0.0-rc.12)(typescript@5.9.3)(xml2js@0.6.2)': dependencies: '@nuxt/devalue': 2.0.2 '@nuxt/kit': 3.21.0(magicast@0.5.1) @@ -11702,7 +11853,7 @@ snapshots: klona: 2.0.6 mocked-exports: 0.1.1 nitropack: 2.13.1(rolldown@1.0.0-rc.12)(xml2js@0.6.2) - nuxt: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) + nuxt: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) ohash: 2.0.11 pathe: 2.0.3 pkg-types: 2.3.0 @@ -11774,7 +11925,7 @@ snapshots: transitivePeerDependencies: - magicast - '@nuxt/vite-builder@3.21.0(@types/node@20.19.31)(eslint@9.39.2(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3))(vue@3.5.27(typescript@5.9.3))(yaml@2.8.2)': + '@nuxt/vite-builder@3.21.0(@types/node@20.19.31)(eslint@9.39.2(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3))(vue@3.5.27(typescript@5.9.3))(yaml@2.8.2)': dependencies: '@nuxt/kit': 3.21.0(magicast@0.5.1) '@rollup/plugin-replace': 6.0.3(rollup@4.57.1) @@ -11794,7 +11945,7 @@ snapshots: magic-string: 0.30.21 mlly: 1.8.0 mocked-exports: 0.1.1 - nuxt: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) + nuxt: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) ohash: 2.0.11 pathe: 2.0.3 perfect-debounce: 2.1.0 @@ -12896,7 +13047,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@sentry/nuxt@10.38.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(rollup@4.57.1)(vue@3.5.27(typescript@5.9.3))': + '@sentry/nuxt@10.38.0(@opentelemetry/api@1.9.0)(@opentelemetry/context-async-hooks@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/core@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/instrumentation@0.211.0(@opentelemetry/api@1.9.0))(@opentelemetry/resources@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/sdk-trace-base@2.5.0(@opentelemetry/api@1.9.0))(@opentelemetry/semantic-conventions@1.39.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(rollup@4.57.1)(vue@3.5.27(typescript@5.9.3))': dependencies: '@nuxt/kit': 3.21.0(magicast@0.5.1) '@sentry/browser': 10.38.0 @@ -12907,7 +13058,7 @@ snapshots: '@sentry/rollup-plugin': 4.9.0(rollup@4.57.1) '@sentry/vite-plugin': 4.9.0 '@sentry/vue': 10.38.0(pinia@3.0.4(typescript@5.9.3)(vue@3.5.27(typescript@5.9.3)))(vue@3.5.27(typescript@5.9.3)) - nuxt: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) + nuxt: 3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2) transitivePeerDependencies: - '@cloudflare/workers-types' - '@opentelemetry/api' @@ -13105,6 +13256,18 @@ snapshots: '@stripe/stripe-js@7.9.0': {} + '@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + eslint: 9.39.2(jiti@1.21.7) + eslint-visitor-keys: 4.2.1 + espree: 10.4.0 + estraverse: 5.3.0 + picomatch: 4.0.3 + transitivePeerDependencies: + - supports-color + - typescript + '@stylistic/eslint-plugin@2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) @@ -13517,6 +13680,22 @@ snapshots: dependencies: '@types/node': 20.19.31 + '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@eslint-community/regexpp': 4.12.2 + '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/type-utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.54.0 + eslint: 9.39.2(jiti@1.21.7) + ignore: 7.0.5 + natural-compare: 1.4.0 + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/eslint-plugin@8.54.0(@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -13533,6 +13712,18 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/scope-manager': 8.54.0 + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.54.0 + debug: 4.4.3 + eslint: 9.39.2(jiti@1.21.7) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/scope-manager': 8.54.0 @@ -13563,6 +13754,18 @@ snapshots: dependencies: typescript: 5.9.3 + '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3)': + dependencies: + '@typescript-eslint/types': 8.54.0 + '@typescript-eslint/typescript-estree': 8.54.0(typescript@5.9.3) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + debug: 4.4.3 + eslint: 9.39.2(jiti@1.21.7) + ts-api-utils: 2.4.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/type-utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.54.0 @@ -13733,6 +13936,12 @@ snapshots: vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue: 3.5.27(typescript@5.9.3) + '@vitejs/plugin-vue@6.0.4(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': + dependencies: + '@rolldown/pluginutils': 1.0.0-rc.2 + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vue: 3.5.27(typescript@5.9.3) + '@vitejs/plugin-vue@6.0.4(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': dependencies: '@rolldown/pluginutils': 1.0.0-rc.2 @@ -14026,14 +14235,14 @@ snapshots: dependencies: '@vue/devtools-kit': 7.7.9 - '@vue/devtools-core@8.0.5(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': + '@vue/devtools-core@8.0.5(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3))': dependencies: '@vue/devtools-kit': 8.0.5 '@vue/devtools-shared': 8.0.5 mitt: 3.0.1 nanoid: 5.1.6 pathe: 2.0.3 - vite-hot-client: 2.1.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite-hot-client: 2.1.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) vue: 3.5.27(typescript@5.9.3) transitivePeerDependencies: - vite @@ -15262,6 +15471,12 @@ snapshots: escape-string-regexp@5.0.0: {} + eslint-config-flat-gitignore@0.3.0(eslint@9.39.2(jiti@1.21.7)): + dependencies: + '@eslint/compat': 1.4.1(eslint@9.39.2(jiti@1.21.7)) + eslint: 9.39.2(jiti@1.21.7) + find-up-simple: 1.0.1 + eslint-config-flat-gitignore@0.3.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint/compat': 1.4.1(eslint@9.39.2(jiti@2.6.1)) @@ -15283,6 +15498,23 @@ snapshots: optionalDependencies: unrs-resolver: 1.11.1 + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3))(eslint@9.39.2(jiti@1.21.7)): + dependencies: + '@typescript-eslint/types': 8.54.0 + comment-parser: 1.4.5 + debug: 4.4.3 + eslint: 9.39.2(jiti@1.21.7) + eslint-import-context: 0.1.9(unrs-resolver@1.11.1) + is-glob: 4.0.3 + minimatch: 10.1.2 + semver: 7.7.3 + stable-hash-x: 0.2.0 + unrs-resolver: 1.11.1 + optionalDependencies: + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) + transitivePeerDependencies: + - supports-color + eslint-plugin-import-x@4.16.1(@typescript-eslint/utils@8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3))(eslint@9.39.2(jiti@2.6.1)): dependencies: '@typescript-eslint/types': 8.54.0 @@ -15300,6 +15532,22 @@ snapshots: transitivePeerDependencies: - supports-color + eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@1.21.7)): + dependencies: + '@es-joy/jsdoccomment': 0.50.2 + are-docs-informative: 0.0.2 + comment-parser: 1.4.1 + debug: 4.4.3 + escape-string-regexp: 4.0.0 + eslint: 9.39.2(jiti@1.21.7) + espree: 10.4.0 + esquery: 1.7.0 + parse-imports-exports: 0.2.4 + semver: 7.7.3 + spdx-expression-parse: 4.0.0 + transitivePeerDependencies: + - supports-color + eslint-plugin-jsdoc@50.8.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@es-joy/jsdoccomment': 0.50.2 @@ -15325,6 +15573,17 @@ snapshots: optionalDependencies: eslint-config-prettier: 10.1.8(eslint@9.39.2(jiti@2.6.1)) + eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@1.21.7)): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) + '@eslint-community/regexpp': 4.12.2 + comment-parser: 1.4.5 + eslint: 9.39.2(jiti@1.21.7) + jsdoc-type-pratt-parser: 4.8.0 + refa: 0.12.1 + regexp-ast-analysis: 0.7.1 + scslre: 0.3.0 + eslint-plugin-regexp@2.10.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -15340,21 +15599,47 @@ snapshots: dependencies: eslint: 9.39.2(jiti@2.6.1) - eslint-plugin-storybook@10.2.4(eslint@9.39.2(jiti@1.21.7))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3): + eslint-plugin-storybook@10.2.4(eslint@9.39.2(jiti@2.6.1))(storybook@10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4))(typescript@5.9.3): dependencies: - '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@1.21.7))(typescript@5.9.3) - eslint: 9.39.2(jiti@1.21.7) + '@typescript-eslint/utils': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint: 9.39.2(jiti@2.6.1) storybook: 10.2.4(@testing-library/dom@10.4.1)(prettier@3.8.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4) transitivePeerDependencies: - supports-color - typescript + eslint-plugin-turbo@2.8.2(eslint@9.39.2(jiti@1.21.7))(turbo@2.8.2): + dependencies: + dotenv: 16.0.3 + eslint: 9.39.2(jiti@1.21.7) + turbo: 2.8.2 + eslint-plugin-turbo@2.8.2(eslint@9.39.2(jiti@2.6.1))(turbo@2.8.2): dependencies: dotenv: 16.0.3 eslint: 9.39.2(jiti@2.6.1) turbo: 2.8.2 + eslint-plugin-unicorn@55.0.0(eslint@9.39.2(jiti@1.21.7)): + dependencies: + '@babel/helper-validator-identifier': 7.28.5 + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) + ci-info: 4.4.0 + clean-regexp: 1.0.0 + core-js-compat: 3.48.0 + eslint: 9.39.2(jiti@1.21.7) + esquery: 1.7.0 + globals: 15.15.0 + indent-string: 4.0.0 + is-builtin-module: 3.2.1 + jsesc: 3.1.0 + pluralize: 8.0.0 + read-pkg-up: 7.0.1 + regexp-tree: 0.1.27 + regjsparser: 0.10.0 + semver: 7.7.3 + strip-indent: 3.0.0 + eslint-plugin-unicorn@55.0.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -15389,6 +15674,20 @@ snapshots: '@stylistic/eslint-plugin': 2.13.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) '@typescript-eslint/parser': 8.54.0(eslint@9.39.2(jiti@2.6.1))(typescript@5.9.3) + eslint-plugin-vue@9.33.0(eslint@9.39.2(jiti@1.21.7)): + dependencies: + '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@1.21.7)) + eslint: 9.39.2(jiti@1.21.7) + globals: 13.24.0 + natural-compare: 1.4.0 + nth-check: 2.1.1 + postcss-selector-parser: 6.1.2 + semver: 7.7.3 + vue-eslint-parser: 9.4.3(eslint@9.39.2(jiti@1.21.7)) + xml-name-validator: 4.0.0 + transitivePeerDependencies: + - supports-color + eslint-plugin-vue@9.33.0(eslint@9.39.2(jiti@2.6.1)): dependencies: '@eslint-community/eslint-utils': 4.9.1(eslint@9.39.2(jiti@2.6.1)) @@ -16415,7 +16714,7 @@ snapshots: dependencies: lie: 3.3.0 pako: 1.0.11 - readable-stream: 2.3.8(patch_hash=h52dazg37p4h3yox67pw36akse) + readable-stream: 2.3.8(patch_hash=3045f7adf989b4e668a4a13819b7285b0de186b79bbf22408acaf2a41c6eaa86) setimmediate: 1.0.5 keep-a-changelog@3.0.2: @@ -16444,7 +16743,7 @@ snapshots: lazystream@1.0.1: dependencies: - readable-stream: 2.3.8(patch_hash=h52dazg37p4h3yox67pw36akse) + readable-stream: 2.3.8(patch_hash=3045f7adf989b4e668a4a13819b7285b0de186b79bbf22408acaf2a41c6eaa86) leac@0.6.0: {} @@ -17450,16 +17749,16 @@ snapshots: dependencies: boolbase: 1.0.0 - nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2): + nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2): dependencies: '@dxup/nuxt': 0.3.2(magicast@0.5.1) '@nuxt/cli': 3.32.0(cac@6.7.14)(magicast@0.5.1) - '@nuxt/devtools': 3.1.1(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) + '@nuxt/devtools': 3.1.1(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)) '@nuxt/kit': 3.21.0(magicast@0.5.1) - '@nuxt/nitro-server': 3.21.0(db0@0.3.4)(ioredis@5.9.2)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(rolldown@1.0.0-rc.12)(typescript@5.9.3)(xml2js@0.6.2) + '@nuxt/nitro-server': 3.21.0(db0@0.3.4)(ioredis@5.9.2)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(rolldown@1.0.0-rc.12)(typescript@5.9.3)(xml2js@0.6.2) '@nuxt/schema': 3.21.0 '@nuxt/telemetry': 2.6.6(magicast@0.5.1) - '@nuxt/vite-builder': 3.21.0(@types/node@20.19.31)(eslint@9.39.2(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3))(vue@3.5.27(typescript@5.9.3))(yaml@2.8.2) + '@nuxt/vite-builder': 3.21.0(@types/node@20.19.31)(eslint@9.39.2(jiti@2.6.1))(lightningcss@1.32.0)(magicast@0.5.1)(nuxt@3.21.0(@parcel/watcher@2.5.6)(@types/node@20.19.31)(@vue/compiler-sfc@3.5.27)(cac@6.7.14)(db0@0.3.4)(eslint@9.39.2(jiti@2.6.1))(ioredis@5.9.2)(lightningcss@1.32.0)(magicast@0.5.1)(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue-tsc@2.2.12(typescript@5.9.3))(xml2js@0.6.2)(yaml@2.8.2))(optionator@0.9.4)(rolldown@1.0.0-rc.12)(rollup@4.57.1)(sass@1.97.3)(terser@5.46.0)(typescript@5.9.3)(vue-tsc@2.2.12(typescript@5.9.3))(vue@3.5.27(typescript@5.9.3))(yaml@2.8.2) '@unhead/vue': 2.1.2(vue@3.5.27(typescript@5.9.3)) '@vue/shared': 3.5.27 c12: 3.3.3(magicast@0.5.1) @@ -18364,7 +18663,7 @@ snapshots: isarray: 0.0.1 string_decoder: 0.10.31 - readable-stream@2.3.8(patch_hash=h52dazg37p4h3yox67pw36akse): + readable-stream@2.3.8(patch_hash=3045f7adf989b4e668a4a13819b7285b0de186b79bbf22408acaf2a41c6eaa86): dependencies: core-util-is: 1.0.3 inherits: 2.0.4 @@ -19657,15 +19956,15 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.3 - vite-dev-rpc@1.1.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + vite-dev-rpc@1.1.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): dependencies: birpc: 2.9.0 - vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) - vite-hot-client: 2.1.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-hot-client: 2.1.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) - vite-hot-client@2.1.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + vite-hot-client@2.1.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): dependencies: - vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vite-node@5.3.0(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): dependencies: @@ -19704,7 +20003,7 @@ snapshots: typescript: 5.9.3 vue-tsc: 2.2.12(typescript@5.9.3) - vite-plugin-inspect@11.3.3(@nuxt/kit@4.3.0(magicast@0.5.1))(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): + vite-plugin-inspect@11.3.3(@nuxt/kit@4.3.0(magicast@0.5.1))(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)): dependencies: ansis: 4.2.0 debug: 4.4.3 @@ -19714,21 +20013,21 @@ snapshots: perfect-debounce: 2.1.0 sirv: 3.0.2 unplugin-utils: 0.3.1 - vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) - vite-dev-rpc: 1.1.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite-dev-rpc: 1.1.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2)) optionalDependencies: '@nuxt/kit': 4.3.0(magicast@0.5.1) transitivePeerDependencies: - supports-color - vite-plugin-vue-tracer@1.2.0(vite@7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)): + vite-plugin-vue-tracer@1.2.0(vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2))(vue@3.5.27(typescript@5.9.3)): dependencies: estree-walker: 3.0.3 exsolve: 1.0.8 magic-string: 0.30.21 pathe: 2.0.3 source-map-js: 1.2.1 - vite: 7.3.1(@types/node@20.19.31)(jiti@2.6.1)(lightningcss@1.32.0)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) + vite: 8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2) vue: 3.5.27(typescript@5.9.3) vite-svg-loader@5.1.0(vue@3.5.27(typescript@5.9.3)): @@ -19782,6 +20081,22 @@ snapshots: terser: 5.46.0 yaml: 2.8.2 + vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@1.21.7)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): + dependencies: + lightningcss: 1.32.0 + picomatch: 4.0.4 + postcss: 8.5.8 + rolldown: 1.0.0-rc.12 + tinyglobby: 0.2.15 + optionalDependencies: + '@types/node': 20.19.31 + esbuild: 0.27.3 + fsevents: 2.3.3 + jiti: 1.21.7 + sass: 1.97.3 + terser: 5.46.0 + yaml: 2.8.2 + vite@8.0.3(@types/node@20.19.31)(esbuild@0.27.3)(jiti@2.6.1)(sass@1.97.3)(terser@5.46.0)(yaml@2.8.2): dependencies: lightningcss: 1.32.0 @@ -19958,6 +20273,19 @@ snapshots: transitivePeerDependencies: - supports-color + vue-eslint-parser@9.4.3(eslint@9.39.2(jiti@1.21.7)): + dependencies: + debug: 4.4.3 + eslint: 9.39.2(jiti@1.21.7) + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.7.0 + lodash: 4.17.23 + semver: 7.7.3 + transitivePeerDependencies: + - supports-color + vue-eslint-parser@9.4.3(eslint@9.39.2(jiti@2.6.1)): dependencies: debug: 4.4.3