diff --git a/.beans/nuzlocke-tracker-2zc9--add-zizmor-and-actionlint-to-ci.md b/.beans/nuzlocke-tracker-2zc9--add-zizmor-and-actionlint-to-ci.md new file mode 100644 index 0000000..732ddd9 --- /dev/null +++ b/.beans/nuzlocke-tracker-2zc9--add-zizmor-and-actionlint-to-ci.md @@ -0,0 +1,17 @@ +--- +# nuzlocke-tracker-2zc9 +title: Add zizmor and actionlint to CI +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:50Z +updated_at: 2026-02-16T19:26:23Z +parent: nuzlocke-tracker-a5es +--- + +Global standards require scanning GitHub Actions workflows with zizmor (security audit) and actionlint (linter). + +## Checklist +- [ ] Add actionlint check to CI +- [ ] Add zizmor scan to CI +- [ ] Fix any issues found \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-44ps--replace-eslintprettier-with-oxlintoxfmt.md b/.beans/nuzlocke-tracker-44ps--replace-eslintprettier-with-oxlintoxfmt.md new file mode 100644 index 0000000..b97a62b --- /dev/null +++ b/.beans/nuzlocke-tracker-44ps--replace-eslintprettier-with-oxlintoxfmt.md @@ -0,0 +1,24 @@ +--- +# nuzlocke-tracker-44ps +title: Replace ESLint/Prettier with oxlint/oxfmt +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:49Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +Global standards require oxlint and oxfmt instead of ESLint and Prettier. This involves: + +## Checklist +- [ ] Install oxlint as devDependency +- [ ] Configure oxlint with typescript, import, unicorn plugins +- [ ] Install oxfmt as devDependency (or use oxlint --fix for formatting) +- [ ] Remove ESLint and all ESLint plugins/configs +- [ ] Remove Prettier and eslint-config-prettier +- [ ] Update package.json scripts +- [ ] Update pre-commit hooks +- [ ] Update CI workflow + +Note: oxfmt may not be stable yet — check current status before proceeding. \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-9vny--add-dependabot-config.md b/.beans/nuzlocke-tracker-9vny--add-dependabot-config.md new file mode 100644 index 0000000..78ed9ef --- /dev/null +++ b/.beans/nuzlocke-tracker-9vny--add-dependabot-config.md @@ -0,0 +1,18 @@ +--- +# nuzlocke-tracker-9vny +title: Add Dependabot config +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:50Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +No .github/dependabot.yml exists. Global standards require Dependabot with 7-day cooldowns and grouped updates. + +## Checklist +- [ ] Create .github/dependabot.yml +- [ ] Configure for npm (frontend), pip (backend), and github-actions +- [ ] Set 7-day schedule intervals +- [ ] Group minor/patch updates \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-a5es--align-repo-config-with-global-dev-standards.md b/.beans/nuzlocke-tracker-a5es--align-repo-config-with-global-dev-standards.md new file mode 100644 index 0000000..32e2e5a --- /dev/null +++ b/.beans/nuzlocke-tracker-a5es--align-repo-config-with-global-dev-standards.md @@ -0,0 +1,11 @@ +--- +# nuzlocke-tracker-a5es +title: Align repo config with global dev standards +status: completed +type: epic +priority: normal +created_at: 2026-02-16T19:13:24Z +updated_at: 2026-02-16T19:26:23Z +--- + +Audit found multiple deviations from the global CLAUDE.md development standards. This epic tracks all the fixes needed. \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-ecij--add-vitest-for-frontend-testing.md b/.beans/nuzlocke-tracker-ecij--add-vitest-for-frontend-testing.md new file mode 100644 index 0000000..d38c8e0 --- /dev/null +++ b/.beans/nuzlocke-tracker-ecij--add-vitest-for-frontend-testing.md @@ -0,0 +1,18 @@ +--- +# nuzlocke-tracker-ecij +title: Add vitest for frontend testing +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:50Z +updated_at: 2026-02-16T19:26:23Z +parent: nuzlocke-tracker-a5es +--- + +No frontend test runner is configured. Global standards require vitest. + +## Checklist +- [ ] Install vitest as devDependency +- [ ] Create vitest.config.ts +- [ ] Add test script to package.json +- [ ] Add test step to CI workflow \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-mn8d--pin-github-actions-to-sha-hashes-and-add-persist-c.md b/.beans/nuzlocke-tracker-mn8d--pin-github-actions-to-sha-hashes-and-add-persist-c.md new file mode 100644 index 0000000..4a5dcaa --- /dev/null +++ b/.beans/nuzlocke-tracker-mn8d--pin-github-actions-to-sha-hashes-and-add-persist-c.md @@ -0,0 +1,18 @@ +--- +# nuzlocke-tracker-mn8d +title: 'Pin GitHub Actions to SHA hashes and add persist-credentials: false' +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:49Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +All GitHub Actions use tag references (@v4, @v5) instead of SHA hashes with version comments. Also missing persist-credentials: false on checkout steps. + +## Checklist +- [ ] Pin actions/checkout to SHA with version comment +- [ ] Pin actions/setup-python to SHA with version comment +- [ ] Pin actions/setup-node to SHA with version comment +- [ ] Add persist-credentials: false to all checkout steps \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-o1ek--fix-ci-python-version-mismatch-and-ruff-target-ver.md b/.beans/nuzlocke-tracker-o1ek--fix-ci-python-version-mismatch-and-ruff-target-ver.md new file mode 100644 index 0000000..fc2184f --- /dev/null +++ b/.beans/nuzlocke-tracker-o1ek--fix-ci-python-version-mismatch-and-ruff-target-ver.md @@ -0,0 +1,17 @@ +--- +# nuzlocke-tracker-o1ek +title: Fix CI Python version mismatch and ruff target-version +status: completed +type: bug +priority: normal +created_at: 2026-02-16T19:13:49Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +CI uses python-version 3.12 but .tool-versions and Docker use 3.14. Also, ruff target-version in pyproject.toml is py312 but should be py314. + +## Checklist +- [ ] Update ci.yml python-version from 3.12 to 3.14 +- [ ] Update pyproject.toml ruff target-version from py312 to py314 +- [ ] Update requires-python to >=3.14 \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-sqb9--pin-frontend-dependencies-to-exact-versions.md b/.beans/nuzlocke-tracker-sqb9--pin-frontend-dependencies-to-exact-versions.md new file mode 100644 index 0000000..b350411 --- /dev/null +++ b/.beans/nuzlocke-tracker-sqb9--pin-frontend-dependencies-to-exact-versions.md @@ -0,0 +1,14 @@ +--- +# nuzlocke-tracker-sqb9 +title: Pin frontend dependencies to exact versions +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:49Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +All frontend dependencies in package.json use ^ or ~ ranges. Global standards require exact pinning (no ^ or ~). + +Pin all dependencies and devDependencies to their currently installed exact versions. \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-w5vu--pin-backend-python-dependencies-to-exact-versions.md b/.beans/nuzlocke-tracker-w5vu--pin-backend-python-dependencies-to-exact-versions.md new file mode 100644 index 0000000..614fdf3 --- /dev/null +++ b/.beans/nuzlocke-tracker-w5vu--pin-backend-python-dependencies-to-exact-versions.md @@ -0,0 +1,14 @@ +--- +# nuzlocke-tracker-w5vu +title: Pin backend Python dependencies to exact versions +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:49Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +All backend dependencies in pyproject.toml use >= ranges. Global standards require exact pins (== not >=). + +Pin all dependencies and dev dependencies to their currently installed exact versions. \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-yyce--add-ty-for-python-type-checking.md b/.beans/nuzlocke-tracker-yyce--add-ty-for-python-type-checking.md new file mode 100644 index 0000000..636a27f --- /dev/null +++ b/.beans/nuzlocke-tracker-yyce--add-ty-for-python-type-checking.md @@ -0,0 +1,18 @@ +--- +# nuzlocke-tracker-yyce +title: Add ty for Python type checking +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:50Z +updated_at: 2026-02-16T19:26:23Z +parent: nuzlocke-tracker-a5es +--- + +Global standards require ty check for static type analysis. Currently not configured. + +## Checklist +- [ ] Add ty to dev dependencies +- [ ] Configure ty rules in pyproject.toml +- [ ] Add ty check step to CI workflow +- [ ] Fix any type errors surfaced \ No newline at end of file diff --git a/.beans/nuzlocke-tracker-zom1--add-missing-tsconfig-strictness-flags.md b/.beans/nuzlocke-tracker-zom1--add-missing-tsconfig-strictness-flags.md new file mode 100644 index 0000000..2ca2622 --- /dev/null +++ b/.beans/nuzlocke-tracker-zom1--add-missing-tsconfig-strictness-flags.md @@ -0,0 +1,19 @@ +--- +# nuzlocke-tracker-zom1 +title: Add missing tsconfig strictness flags +status: completed +type: task +priority: normal +created_at: 2026-02-16T19:13:49Z +updated_at: 2026-02-16T19:24:15Z +parent: nuzlocke-tracker-a5es +--- + +tsconfig.app.json is missing 4 required strict flags from the global standards: + +- noUncheckedIndexedAccess: true +- exactOptionalPropertyTypes: true +- noImplicitOverride: true +- noPropertyAccessFromIndexSignature: true + +These need to be added and any resulting type errors fixed. \ No newline at end of file diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..ba2a624 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,31 @@ +version: 2 + +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + groups: + actions: + patterns: + - "*" + + - package-ecosystem: "npm" + directory: "/frontend" + schedule: + interval: "weekly" + groups: + minor-and-patch: + update-types: + - "minor" + - "patch" + + - package-ecosystem: "pip" + directory: "/backend" + schedule: + interval: "weekly" + groups: + minor-and-patch: + update-types: + - "minor" + - "patch" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f79340..8a95e8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -22,21 +22,45 @@ jobs: backend-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 with: - python-version: "3.12" - - run: pip install ruff + persist-credentials: false + - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0 + with: + python-version: "3.14" + - run: pip install ruff ty - name: Check linting run: ruff check backend/ - name: Check formatting run: ruff format --check backend/ + - name: Type check + run: ty check backend/src/ + continue-on-error: true + + actions-lint: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + - name: Install actionlint + run: | + curl -sL https://github.com/rhysd/actionlint/releases/latest/download/actionlint_linux_amd64.tar.gz | tar xz + sudo mv actionlint /usr/local/bin/ + - name: Lint GitHub Actions + run: actionlint + - name: Install zizmor + run: pip install zizmor + - name: Audit GitHub Actions security + run: zizmor .github/workflows/ frontend-lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false + - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: "24" - name: Install dependencies @@ -46,7 +70,7 @@ jobs: run: npm run lint working-directory: frontend - name: Check formatting - run: npx prettier --check "src/**/*.{ts,tsx,css,json}" + run: npx oxfmt --check "src/" working-directory: frontend - name: Type check run: npx tsc -b diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index cd4a9c2..8b08735 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -8,7 +8,9 @@ jobs: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4.3.1 + with: + persist-credentials: false - name: Login to Gitea registry run: echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login gitea.nerdboden.de -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin diff --git a/.gitignore b/.gitignore index 495a352..61d59d6 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,28 @@ temp/ # Local config overrides *.local + +# Claude Code sandbox artifacts +/HEAD +/config +/hooks +/objects +/refs +/frontend/HEAD +/frontend/config +/frontend/hooks +/frontend/objects +/frontend/refs +/.gitmodules +/.gitconfig +/.bash_profile +/.bashrc +/.profile +/.zprofile +/.zshrc +/.ripgreprc +/.mcp.json +/.claude/agents +/.claude/commands +/.claude/skills +/frontend/.claude/ diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 2640044..372260e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -12,18 +12,18 @@ repos: # Frontend (TypeScript/React) — local hooks using project node_modules - repo: local hooks: - - id: eslint - name: eslint - entry: npx eslint + - id: oxlint + name: oxlint + entry: npx oxlint -c frontend/.oxlintrc.json language: system files: ^frontend/src/.*\.(ts|tsx)$ pass_filenames: true - - id: prettier - name: prettier - entry: npx prettier --check + - id: oxfmt + name: oxfmt + entry: npx oxfmt --check --config frontend/.oxfmtrc.json language: system - files: ^frontend/src/.*\.(ts|tsx|css|json)$ + files: ^frontend/src/.*\.(ts|tsx)$ pass_filenames: true - id: tsc diff --git a/CLAUDE.md b/CLAUDE.md index 5b90c79..30d3390 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -16,7 +16,7 @@ This project uses [pre-commit](https://pre-commit.com/) to run linting and forma **Hooks configured:** - **Backend:** `ruff check --fix` and `ruff format` on Python files under `backend/` -- **Frontend:** `eslint`, `prettier --check`, and `tsc -b` on files under `frontend/` +- **Frontend:** `oxlint`, `oxfmt --check`, and `tsc -b` on files under `frontend/` Frontend hooks require `npm ci` in `frontend/` first (they use `npx` to run from local `node_modules`). diff --git a/backend/pyproject.toml b/backend/pyproject.toml index e4069a2..10d7d9a 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -3,25 +3,26 @@ name = "nuzlocke-tracker-api" version = "0.1.0" description = "Backend API for Nuzlocke Tracker" readme = "README.md" -requires-python = ">=3.12" +requires-python = ">=3.14" dependencies = [ - "fastapi>=0.115.0", - "uvicorn[standard]>=0.34.0", - "pydantic>=2.10.0", - "pydantic-settings>=2.7.0", - "python-dotenv>=1.0.0", - "sqlalchemy[asyncio]>=2.0.0", - "asyncpg>=0.30.0", - "alembic>=1.14.0", + "fastapi==0.128.4", + "uvicorn[standard]==0.40.0", + "pydantic==2.12.5", + "pydantic-settings==2.12.0", + "python-dotenv==1.2.1", + "sqlalchemy[asyncio]==2.0.46", + "asyncpg==0.31.0", + "alembic==1.18.3", ] [project.optional-dependencies] dev = [ - "ruff>=0.9.0", - "pre-commit>=4.0.0", - "pytest>=8.0.0", - "pytest-asyncio>=0.25.0", - "httpx>=0.28.0", + "ruff==0.15.0", + "ty==0.0.17", + "pre-commit==4.5.1", + "pytest==9.0.2", + "pytest-asyncio==1.3.0", + "httpx==0.28.1", ] [build-system] @@ -32,7 +33,7 @@ build-backend = "hatchling.build" packages = ["src/app"] [tool.ruff] -target-version = "py312" +target-version = "py314" line-length = 88 [tool.ruff.lint] @@ -57,6 +58,12 @@ ignore = [ [tool.ruff.lint.isort] known-first-party = ["app"] +[tool.ty.environment] +python-version = "3.14" + +[tool.ty.src] +root = "src" + [tool.pytest.ini_options] asyncio_mode = "auto" testpaths = ["tests"] diff --git a/frontend/.prettierrc b/frontend/.oxfmtrc.json similarity index 100% rename from frontend/.prettierrc rename to frontend/.oxfmtrc.json diff --git a/frontend/.oxlintrc.json b/frontend/.oxlintrc.json new file mode 100644 index 0000000..9a671f4 --- /dev/null +++ b/frontend/.oxlintrc.json @@ -0,0 +1,9 @@ +{ + "plugins": ["typescript", "import", "unicorn", "react"], + "rules": { + "react/exhaustive-deps": "warn", + "react/rules-of-hooks": "error", + "unicorn/no-null": "off" + }, + "ignorePatterns": ["dist"] +} diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js deleted file mode 100644 index 52e80ee..0000000 --- a/frontend/eslint.config.js +++ /dev/null @@ -1,33 +0,0 @@ -import js from '@eslint/js' -import globals from 'globals' -import reactHooks from 'eslint-plugin-react-hooks' -import reactRefresh from 'eslint-plugin-react-refresh' -import tseslint from 'typescript-eslint' -import eslintConfigPrettier from 'eslint-config-prettier' -import { defineConfig, globalIgnores } from 'eslint/config' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - js.configs.recommended, - tseslint.configs.recommended, - reactHooks.configs.flat.recommended, - reactRefresh.configs.vite, - eslintConfigPrettier, - ], - languageOptions: { - ecmaVersion: 2020, - globals: globals.browser, - }, - rules: { - 'react-refresh/only-export-components': [ - 'warn', - { allowConstantExport: true }, - ], - 'react-hooks/set-state-in-effect': 'off', - 'react-hooks/preserve-manual-memoization': 'off', - }, - }, -]) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 686b17f..b786304 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -8,32 +8,27 @@ "name": "nuzlocke-tracker-frontend", "version": "0.0.0", "dependencies": { - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^10.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@tanstack/react-query": "^5.90.20", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "react-router-dom": "^7.13.0", - "sonner": "^2.0.7" + "@dnd-kit/core": "6.3.1", + "@dnd-kit/sortable": "10.0.0", + "@dnd-kit/utilities": "3.2.2", + "@tanstack/react-query": "5.90.20", + "react": "19.2.4", + "react-dom": "19.2.4", + "react-router-dom": "7.13.0", + "sonner": "2.0.7" }, "devDependencies": { - "@eslint/js": "^9.39.1", - "@tailwindcss/vite": "^4.1.18", - "@types/node": "^24.10.1", - "@types/react": "^19.2.5", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "eslint": "^9.39.1", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^16.5.0", - "prettier": "^3.8.1", - "tailwindcss": "^4.1.18", - "typescript": "~5.9.3", - "typescript-eslint": "^8.46.4", - "vite": "^7.2.4" + "@tailwindcss/vite": "4.1.18", + "@types/node": "24.10.10", + "@types/react": "19.2.11", + "@types/react-dom": "19.2.3", + "@vitejs/plugin-react": "5.1.3", + "oxfmt": "0.33.0", + "oxlint": "1.48.0", + "tailwindcss": "4.1.18", + "typescript": "5.9.3", + "vite": "7.3.1", + "vitest": "^4.0.18" } }, "node_modules/@babel/code-frame": { @@ -815,215 +810,6 @@ "node": ">=18" } }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.1", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", - "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.7", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/config-helpers": { - "version": "0.4.2", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", - "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/core": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", - "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz", - "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.1", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/js": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz", - "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - } - }, - "node_modules/@eslint/object-schema": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", - "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/plugin-kit": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", - "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.17.0", - "levn": "^0.4.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" - }, - "engines": { - "node": ">=18.18.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=18.18" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", @@ -1074,6 +860,652 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, + "node_modules/@oxfmt/binding-android-arm-eabi": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm-eabi/-/binding-android-arm-eabi-0.33.0.tgz", + "integrity": "sha512-ML6qRW8/HiBANteqfyFAR1Zu0VrJu+6o4gkPLsssq74hQ7wDMkufBYJXI16PGSERxEYNwKxO5fesCuMssgTv9w==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-android-arm64": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-android-arm64/-/binding-android-arm64-0.33.0.tgz", + "integrity": "sha512-WimmcyrGpTOntj7F7CO9RMssncOKYall93nBnzJbI2ZZDhVRuCkvFwTpwz80cZqwYm5udXRXfF40ZXcCxjp9jg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-darwin-arm64": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-arm64/-/binding-darwin-arm64-0.33.0.tgz", + "integrity": "sha512-PorspsX9O5ISstVaq34OK4esN0LVcuU4DVg+XuSqJsfJ//gn6z6WH2Tt7s0rTQaqEcp76g7+QdWQOmnJDZsEVg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-darwin-x64": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-darwin-x64/-/binding-darwin-x64-0.33.0.tgz", + "integrity": "sha512-8278bqQtOcHRPhhzcqwN9KIideut+cftBjF8d2TOsSQrlsJSFx41wCCJ38mFmH9NOmU1M+x9jpeobHnbRP1okw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-freebsd-x64": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-freebsd-x64/-/binding-freebsd-x64-0.33.0.tgz", + "integrity": "sha512-BiqYVwWFHLf5dkfg0aCKsXa9rpi//vH1+xePCpd7Ulz9yp9pJKP4DWgS5g+OW8MaqOtt7iyAszhxtk/j1nDKHQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm-gnueabihf": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-0.33.0.tgz", + "integrity": "sha512-oAVmmurXx0OKbNOVv71oK92LsF1LwYWpnhDnX0VaAy/NLsCKf4B7Zo7lxkJh80nfhU20TibcdwYfoHVaqlStPQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm-musleabihf": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-0.33.0.tgz", + "integrity": "sha512-YB6S8CiRol59oRxnuclJiWoV6l+l8ru/NsuQNYjXZnnPXfSTXKtMLWHCnL/figpCFYA1E7JyjrBbar1qxe2aZg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm64-gnu": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-0.33.0.tgz", + "integrity": "sha512-hrYy+FpWoB6N24E9oGRimhVkqlls9yeqcRmQakEPUHoAbij6rYxsHHYIp3+FHRiQZFAOUxWKn/CCQoy/Mv3Dgw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-arm64-musl": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-arm64-musl/-/binding-linux-arm64-musl-0.33.0.tgz", + "integrity": "sha512-O1YIzymGRdWj9cG5iVTjkP7zk9/hSaVN8ZEbqMnWZjLC1phXlv54cUvANGGXndgJp2JS4W9XENn7eo5I4jZueg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-ppc64-gnu": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-0.33.0.tgz", + "integrity": "sha512-2lrkNe+B0w1tCgQTaozfUNQCYMbqKKCGcnTDATmWCZzO77W2sh+3n04r1lk9Q1CK3bI+C3fPwhFPUR2X2BvlyQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-riscv64-gnu": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-0.33.0.tgz", + "integrity": "sha512-8DSG1q0M6097vowHAkEyHnKed75/BWr1IBtgCJfytnWQg+Jn1X4DryhfjqonKZOZiv74oFQl5J8TCbdDuXXdtQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-riscv64-musl": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-0.33.0.tgz", + "integrity": "sha512-eWaxnpPz7+p0QGUnw7GGviVBDOXabr6Cd0w7S/vnWTqQo9z1VroT7XXFnJEZ3dBwxMB9lphyuuYi/GLTCxqxlg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-s390x-gnu": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-0.33.0.tgz", + "integrity": "sha512-+mH8cQTqq+Tu2CdoB2/Wmk9CqotXResi+gPvXpb+AAUt/LiwpicTQqSolMheQKogkDTYHPuUiSN23QYmy7IXNQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-x64-gnu": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-gnu/-/binding-linux-x64-gnu-0.33.0.tgz", + "integrity": "sha512-fjyslAYAPE2+B6Ckrs5LuDQ6lB1re5MumPnzefAXsen3JGwiRilra6XdjUmszTNoExJKbewoxxd6bcLSTpkAJQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-linux-x64-musl": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-linux-x64-musl/-/binding-linux-x64-musl-0.33.0.tgz", + "integrity": "sha512-ve/jGBlTt35Jl/I0A0SfCQX3wKnadzPDdyOFEwe2ZgHHIT9uhqhAv1PaVXTenSBpauICEWYH8mWy+ittzlVE/A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-openharmony-arm64": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-openharmony-arm64/-/binding-openharmony-arm64-0.33.0.tgz", + "integrity": "sha512-lsWRgY9e+uPvwXnuDiJkmJ2Zs3XwwaQkaALJ3/SXU9kjZP0Qh8/tGW8Tk/Z6WL32sDxx+aOK5HuU7qFY9dHJhg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-arm64-msvc": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-0.33.0.tgz", + "integrity": "sha512-w8AQHyGDRZutxtQ7IURdBEddwFrtHQiG6+yIFpNJ4HiMyYEqeAWzwBQBfwSAxtSNh6Y9qqbbc1OM2mHN6AB3Uw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-ia32-msvc": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-0.33.0.tgz", + "integrity": "sha512-j2X4iumKVwDzQtUx3JBDkaydx6eLuncgUZPl2ybZ8llxJMFbZIniws70FzUQePMfMtzLozIm7vo4bjkvQFsOzw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxfmt/binding-win32-x64-msvc": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/@oxfmt/binding-win32-x64-msvc/-/binding-win32-x64-msvc-0.33.0.tgz", + "integrity": "sha512-lsBQxbepASwOBUh3chcKAjU+jVAQhLElbPYiagIq26cU8vA9Bttj6t20bMvCQCw31m440IRlNhrK7NpnUI8mzA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm-eabi": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm-eabi/-/binding-android-arm-eabi-1.48.0.tgz", + "integrity": "sha512-1Pz/stJvveO9ZO7ll4ZoEY3f6j2FiUgBLBcCRCiW6ylId9L9UKs+gn3X28m3eTnoiFCkhKwmJJ+VO6vwsu7Qtg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-android-arm64": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-android-arm64/-/binding-android-arm64-1.48.0.tgz", + "integrity": "sha512-Zc42RWGE8huo6Ht0lXKjd0NH2lWNmimQHUmD0JFcvShLOuwN+RSEE/kRakc2/0LIgOUuU/R7PaDMCOdQlPgNUQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-arm64": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-arm64/-/binding-darwin-arm64-1.48.0.tgz", + "integrity": "sha512-jgZs563/4vaG5jH2RSt2TSh8A2jwsFdmhLXrElMdm3Mmto0HPf85FgInLSNi9HcwzQFvkYV8JofcoUg2GH1HTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-darwin-x64": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-darwin-x64/-/binding-darwin-x64-1.48.0.tgz", + "integrity": "sha512-kvo87BujEUjCJREuWDC4aPh1WoXCRFFWE4C7uF6wuoMw2f6N2hypA/cHHcYn9DdL8R2RrgUZPefC8JExyeIMKA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-freebsd-x64": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-freebsd-x64/-/binding-freebsd-x64-1.48.0.tgz", + "integrity": "sha512-eyzzPaHQKn0RIM+ueDfgfJF2RU//Wp4oaKs2JVoVYcM5HjbCL36+O0S3wO5Xe1NWpcZIG3cEHc/SuOCDRqZDSg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-gnueabihf": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.48.0.tgz", + "integrity": "sha512-p3kSloztK7GRO7FyO3u38UCjZxQTl92VaLDsMQAq0eGoiNmeeEF1KPeE4+Fr+LSkQhF8WvJKSuls6TwOlurdPA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm-musleabihf": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm-musleabihf/-/binding-linux-arm-musleabihf-1.48.0.tgz", + "integrity": "sha512-uWM+wiTqLW/V0ZmY/eyTWs8ykhIkzU+K2tz/8m35YepYEzohiUGRbnkpAFXj2ioXpQL+GUe5vmM3SLH6ozlfFw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-gnu": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.48.0.tgz", + "integrity": "sha512-OhQNPjs/OICaYqxYJjKKMaIY7p3nJ9IirXcFoHKD+CQE1BZFCeUUAknMzUeLclDCfudH9Vb/UgjFm8+ZM5puAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-arm64-musl": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.48.0.tgz", + "integrity": "sha512-adu5txuwGvQ4C4fjYHJD+vnY+OCwCixBzn7J3KF3iWlVHBBImcosSv+Ye+fbMMJui4HGjifNXzonjKm9pXmOiw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-ppc64-gnu": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.48.0.tgz", + "integrity": "sha512-inlQQRUnHCny/7b7wA6NjEoJSSZPNea4qnDhWyeqBYWx8ukf2kzNDSiamfhOw6bfAYPm/PVlkVRYaNXQbkLeTQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-gnu": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-gnu/-/binding-linux-riscv64-gnu-1.48.0.tgz", + "integrity": "sha512-YiJx6sW6bYebQDZRVWLKm/Drswx/hcjIgbLIhULSn0rRcBKc7d9V6mkqPjKDbhcxJgQD5Zi0yVccJiOdF40AWA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-riscv64-musl": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-riscv64-musl/-/binding-linux-riscv64-musl-1.48.0.tgz", + "integrity": "sha512-zwSqxMgmb2ITamNfDv9Q9EKBc/4ZhCBP9gkg2hhcgR6sEVGPUDl1AKPC89CBKMxkmPUi3685C38EvqtZn5OtHw==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-s390x-gnu": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.48.0.tgz", + "integrity": "sha512-c/+2oUWAOsQB5JTem0rW8ODlZllF6pAtGSGXoLSvPTonKI1vAwaKhD9Qw1X36jRbcI3Etkpu/9z/RRjMba8vFQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-gnu": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.48.0.tgz", + "integrity": "sha512-PhauDqeFW5DGed6QxCY5lXZYKSlcBdCXJnH03ZNU6QmDZ0BFM/zSy1oPT2MNb1Afx1G6yOOVk8ErjWsQ7c59ng==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-linux-x64-musl": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-linux-x64-musl/-/binding-linux-x64-musl-1.48.0.tgz", + "integrity": "sha512-6d7LIFFZGiavbHndhf1cK9kG9qmy2Dmr37sV9Ep7j3H+ciFdKSuOzdLh85mEUYMih+b+esMDlF5DU0WQRZPQjw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-openharmony-arm64": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-openharmony-arm64/-/binding-openharmony-arm64-1.48.0.tgz", + "integrity": "sha512-r+0KK9lK6vFp3tXAgDMOW32o12dxvKS3B9La1uYMGdWAMoSeu2RzG34KmzSpXu6MyLDl4aSVyZLFM8KGdEjwaw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-arm64-msvc": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.48.0.tgz", + "integrity": "sha512-Nkw/MocyT3HSp0OJsKPXrcbxZqSPMTYnLLfsqsoiFKoL1ppVNL65MFa7vuTxJehPlBkjy+95gUgacZtuNMECrg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-ia32-msvc": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-ia32-msvc/-/binding-win32-ia32-msvc-1.48.0.tgz", + "integrity": "sha512-reO1SpefvRmeZSP+WeyWkQd1ArxxDD1MyKgMUKuB8lNuUoxk9QEohYtKnsfsxJuFwMT0JTr7p9wZjouA85GzGQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@oxlint/binding-win32-x64-msvc": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/@oxlint/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.48.0.tgz", + "integrity": "sha512-T6zwhfcsrorqAybkOglZdPkTLlEwipbtdO1qjE+flbawvwOMsISoyiuaa7vM7zEyfq1hmDvMq1ndvkYFioranA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, "node_modules/@rolldown/pluginutils": { "version": "1.0.0-rc.2", "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.2.tgz", @@ -1431,6 +1863,13 @@ "win32" ] }, + "node_modules/@standard-schema/spec": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.1.0.tgz", + "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==", + "dev": true, + "license": "MIT" + }, "node_modules/@tailwindcss/node": { "version": "4.1.18", "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.18.tgz", @@ -1774,6 +2213,24 @@ "@babel/types": "^7.28.2" } }, + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" + } + }, + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1781,13 +2238,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true, - "license": "MIT" - }, "node_modules/@types/node": { "version": "24.10.10", "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.10.tgz", @@ -1820,276 +2270,6 @@ "@types/react": "^19.2.0" } }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.54.0.tgz", - "integrity": "sha512-hAAP5io/7csFStuOmR782YmTthKBJ9ND3WVL60hcOjvtGFb+HJxH4O5huAcmcZ9v9G8P+JETiZ/G1B8MALnWZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/regexpp": "^4.12.2", - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/type-utils": "8.54.0", - "@typescript-eslint/utils": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", - "ignore": "^7.0.5", - "natural-compare": "^1.4.0", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^8.54.0", - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { - "version": "7.0.5", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", - "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.54.0.tgz", - "integrity": "sha512-BtE0k6cjwjLZoZixN0t5AKP0kSzlGu7FctRXYuPAm//aaiZhmfq1JwdYpYr1brzEspYyFeF+8XF5j2VK6oalrA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/project-service": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.54.0.tgz", - "integrity": "sha512-YPf+rvJ1s7MyiWM4uTRhE4DvBXrEV+d8oC3P9Y2eT7S+HBS0clybdMIPnhiATi9vZOYDc7OQ1L/i6ga6NFYK/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/tsconfig-utils": "^8.54.0", - "@typescript-eslint/types": "^8.54.0", - "debug": "^4.4.3" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.54.0.tgz", - "integrity": "sha512-27rYVQku26j/PbHYcVfRPonmOlVI6gihHtXFbTdB5sb6qA0wdAQAbyXFVarQ5t4HRojIz64IV90YtsjQSSGlQg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/tsconfig-utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.54.0.tgz", - "integrity": "sha512-dRgOyT2hPk/JwxNMZDsIXDgyl9axdJI3ogZ2XWhBPsnZUv+hPesa5iuhdYt2gzwA9t8RE5ytOJ6xB0moV0Ujvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.54.0.tgz", - "integrity": "sha512-hiLguxJWHjjwL6xMBwD903ciAwd7DmK30Y9Axs/etOkftC3ZNN9K44IuRD/EB08amu+Zw6W37x9RecLkOo3pMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0", - "@typescript-eslint/utils": "8.54.0", - "debug": "^4.4.3", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.54.0.tgz", - "integrity": "sha512-PDUI9R1BVjqu7AUDsRBbKMtwmjWcn4J3le+5LpcFgWULN3LvHC5rkc9gCVxbrsrGmO1jfPybN5s6h4Jy+OnkAA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.54.0.tgz", - "integrity": "sha512-BUwcskRaPvTk6fzVWgDPdUndLjB87KYDrN5EYGetnktoeAvPtO4ONHlAZDnj5VFnUANg0Sjm7j4usBlnoVMHwA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/project-service": "8.54.0", - "@typescript-eslint/tsconfig-utils": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/visitor-keys": "8.54.0", - "debug": "^4.4.3", - "minimatch": "^9.0.5", - "semver": "^7.7.3", - "tinyglobby": "^0.2.15", - "ts-api-utils": "^2.4.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", - "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.54.0.tgz", - "integrity": "sha512-9Cnda8GS57AQakvRyG0PTejJNlA2xhvyNtEVIMlDWOOeEyBkYWhGPnfrIAnqxLMTSTo6q8g12XVjjev5l1NvMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@eslint-community/eslint-utils": "^4.9.1", - "@typescript-eslint/scope-manager": "8.54.0", - "@typescript-eslint/types": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.54.0.tgz", - "integrity": "sha512-VFlhGSl4opC0bprJiItPQ1RfUhGDIBokcPwaFH4yiBCaNPeld/9VeXbiPO1cLyorQi1G1vL+ecBk1x8o1axORA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "8.54.0", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, "node_modules/@vitejs/plugin-react": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.3.tgz", @@ -2111,76 +2291,126 @@ "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" } }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "node_modules/@vitest/expect": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-4.0.18.tgz", + "integrity": "sha512-8sCWUyckXXYvx4opfzVY03EOiYVxyNrHS5QxX3DAIi5dpJAAkyJezHCP77VMX4HKA2LDT/Jpfo8i2r5BE3GnQQ==", "dev": true, "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" + "dependencies": { + "@standard-schema/spec": "^1.0.0", + "@types/chai": "^5.2.2", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "chai": "^6.2.1", + "tinyrainbow": "^3.0.3" }, - "engines": { - "node": ">=0.4.0" + "funding": { + "url": "https://opencollective.com/vitest" } }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "node_modules/@vitest/mocker": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-4.0.18.tgz", + "integrity": "sha512-HhVd0MDnzzsgevnOWCBj5Otnzobjy5wLBe4EdeeFGv8luMsGcYqDuFRMcttKWZA5vVO8RFjexVovXvAM4JoJDQ==", "dev": true, "license": "MIT", + "dependencies": { + "@vitest/spy": "4.0.18", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.21" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "msw": "^2.4.9", + "vite": "^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@vitest/pretty-format": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-4.0.18.tgz", + "integrity": "sha512-P24GK3GulZWC5tz87ux0m8OADrQIUVDPIjjj65vBXYG17ZeU3qD7r+MNZ1RNv4l8CGU2vtTRqixrOi9fYk/yKw==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" + "tinyrainbow": "^3.0.3" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "url": "https://opencollective.com/vitest" } }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@vitest/runner": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-4.0.18.tgz", + "integrity": "sha512-rpk9y12PGa22Jg6g5M3UVVnTS7+zycIGk9ZNGN+m6tZHKQb7jrP7/77WfZy13Y/EUDd52NDsLRQhYKtv7XfPQw==", "dev": true, "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" + "@vitest/utils": "4.0.18", + "pathe": "^2.0.3" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://opencollective.com/vitest" } }, - "node_modules/argparse": { + "node_modules/@vitest/snapshot": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-4.0.18.tgz", + "integrity": "sha512-PCiV0rcl7jKQjbgYqjtakly6T1uwv/5BQ9SwBLekVg/EaYeQFPiXcgrC2Y7vDMA8dM1SUEAEV82kgSQIlXNMvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "magic-string": "^0.30.21", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-4.0.18.tgz", + "integrity": "sha512-cbQt3PTSD7P2OARdVW3qWER5EGq7PHlvE+QfzSC0lbwO+xnt7+XH06ZzFjFRgzUX//JmpxrCu92VdwvEPlWSNw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/utils": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-4.0.18.tgz", + "integrity": "sha512-msMRKLMVLWygpK3u2Hybgi4MNjcYJvwTb0Ru09+fOyCXIgT5raYP041DRRdiJiI3k/2U6SEbAETB3YtBrUkCFA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "4.0.18", + "tinyrainbow": "^3.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/assertion-error": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", "dev": true, - "license": "Python-2.0" - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=12" + } }, "node_modules/baseline-browser-mapping": { "version": "2.9.19", @@ -2192,17 +2422,6 @@ "baseline-browser-mapping": "dist/cli.js" } }, - "node_modules/brace-expansion": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", - "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, "node_modules/browserslist": { "version": "4.28.1", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", @@ -2238,16 +2457,6 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/caniuse-lite": { "version": "1.0.30001767", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001767.tgz", @@ -2269,50 +2478,16 @@ ], "license": "CC-BY-4.0" }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/chai": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "node": ">=18" } }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -2333,21 +2508,6 @@ "url": "https://opencollective.com/express" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -2373,13 +2533,6 @@ } } }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, "node_modules/detect-libc": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", @@ -2411,6 +2564,13 @@ "node": ">=10.13.0" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "dev": true, + "license": "MIT" + }, "node_modules/esbuild": { "version": "0.27.2", "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", @@ -2463,241 +2623,26 @@ "node": ">=6" } }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "9.39.2", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz", - "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.8.0", - "@eslint-community/regexpp": "^4.12.1", - "@eslint/config-array": "^0.21.1", - "@eslint/config-helpers": "^0.4.2", - "@eslint/core": "^0.17.0", - "@eslint/eslintrc": "^3.3.1", - "@eslint/js": "9.39.2", - "@eslint/plugin-kit": "^0.4.1", - "@humanfs/node": "^0.16.6", - "@humanwhocodes/module-importer": "^1.0.1", - "@humanwhocodes/retry": "^0.4.2", - "@types/estree": "^1.0.6", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.6", - "debug": "^4.3.2", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^8.4.0", - "eslint-visitor-keys": "^4.2.1", - "espree": "^10.4.0", - "esquery": "^1.5.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^8.0.0", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://eslint.org/donate" - }, - "peerDependencies": { - "jiti": "*" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - } - } - }, - "node_modules/eslint-config-prettier": { - "version": "10.1.8", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.8.tgz", - "integrity": "sha512-82GZUjRS0p/jganf6q1rEO25VSoHH0hKPCTrgillPjdI/3bgBhAE1QzHrHTizjpRvy6pGAvKjDJtk2pF9NDq8w==", - "dev": true, - "license": "MIT", - "bin": { - "eslint-config-prettier": "bin/cli.js" - }, - "funding": { - "url": "https://opencollective.com/eslint-config-prettier" - }, - "peerDependencies": { - "eslint": ">=7.0.0" - } - }, - "node_modules/eslint-plugin-react-hooks": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", - "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.24.4", - "@babel/parser": "^7.24.4", - "hermes-parser": "^0.25.1", - "zod": "^3.25.0 || ^4.0.0", - "zod-validation-error": "^3.5.0 || ^4.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + "@types/estree": "^1.0.0" } }, - "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.26", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", - "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "eslint": ">=8.40" - } - }, - "node_modules/eslint-scope": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", - "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", - "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "node_modules/expect-type": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", + "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=12.0.0" } }, - "node_modules/espree": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", - "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "acorn": "^8.15.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^4.2.1" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", - "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" - }, "node_modules/fdir": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", @@ -2716,57 +2661,6 @@ } } }, - "node_modules/file-entry-cache": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", - "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "flat-cache": "^4.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", - "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", - "dev": true, - "license": "MIT", - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.4" - }, - "engines": { - "node": ">=16" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true, - "license": "ISC" - }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -2792,32 +2686,6 @@ "node": ">=6.9.0" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "16.5.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", - "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -2825,100 +2693,6 @@ "dev": true, "license": "ISC" }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hermes-estree": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", - "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", - "dev": true, - "license": "MIT" - }, - "node_modules/hermes-parser": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", - "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hermes-estree": "0.25.1" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, "node_modules/jiti": { "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", @@ -2936,19 +2710,6 @@ "dev": true, "license": "MIT" }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -2962,27 +2723,6 @@ "node": ">=6" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true, - "license": "MIT" - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -2996,30 +2736,6 @@ "node": ">=6" } }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "license": "MIT", - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/lightningcss": { "version": "1.30.2", "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.2.tgz", @@ -3281,29 +2997,6 @@ "url": "https://opencollective.com/parcel" } }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -3324,19 +3017,6 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -3363,13 +3043,6 @@ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true, - "license": "MIT" - }, "node_modules/node-releases": { "version": "2.0.27", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", @@ -3377,88 +3050,108 @@ "dev": true, "license": "MIT" }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "node_modules/obug": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.1.1.tgz", + "integrity": "sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ==", "dev": true, - "license": "MIT", - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], + "license": "MIT" }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "node_modules/oxfmt": { + "version": "0.33.0", + "resolved": "https://registry.npmjs.org/oxfmt/-/oxfmt-0.33.0.tgz", + "integrity": "sha512-ogxBXA9R4BFeo8F1HeMIIxHr5kGnQwKTYZ5k131AEGOq1zLxInNhvYSpyRQ+xIXVMYfCN7yZHKff/lb5lp4auQ==", "dev": true, "license": "MIT", "dependencies": { - "yocto-queue": "^0.1.0" + "tinypool": "2.1.0" + }, + "bin": { + "oxfmt": "bin/oxfmt" }, "engines": { - "node": ">=10" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/Boshen" + }, + "optionalDependencies": { + "@oxfmt/binding-android-arm-eabi": "0.33.0", + "@oxfmt/binding-android-arm64": "0.33.0", + "@oxfmt/binding-darwin-arm64": "0.33.0", + "@oxfmt/binding-darwin-x64": "0.33.0", + "@oxfmt/binding-freebsd-x64": "0.33.0", + "@oxfmt/binding-linux-arm-gnueabihf": "0.33.0", + "@oxfmt/binding-linux-arm-musleabihf": "0.33.0", + "@oxfmt/binding-linux-arm64-gnu": "0.33.0", + "@oxfmt/binding-linux-arm64-musl": "0.33.0", + "@oxfmt/binding-linux-ppc64-gnu": "0.33.0", + "@oxfmt/binding-linux-riscv64-gnu": "0.33.0", + "@oxfmt/binding-linux-riscv64-musl": "0.33.0", + "@oxfmt/binding-linux-s390x-gnu": "0.33.0", + "@oxfmt/binding-linux-x64-gnu": "0.33.0", + "@oxfmt/binding-linux-x64-musl": "0.33.0", + "@oxfmt/binding-openharmony-arm64": "0.33.0", + "@oxfmt/binding-win32-arm64-msvc": "0.33.0", + "@oxfmt/binding-win32-ia32-msvc": "0.33.0", + "@oxfmt/binding-win32-x64-msvc": "0.33.0" } }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/oxlint": { + "version": "1.48.0", + "resolved": "https://registry.npmjs.org/oxlint/-/oxlint-1.48.0.tgz", + "integrity": "sha512-m5vyVBgPtPhVCJc3xI//8je9lRc8bYuYB4R/1PH3VPGOjA4vjVhkHtyJukdEjYEjwrw4Qf1eIf+pP9xvfhfMow==", "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" + "bin": { + "oxlint": "bin/oxlint" }, "engines": { - "node": ">=10" + "node": "^20.19.0 || >=22.12.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" + "url": "https://github.com/sponsors/Boshen" }, - "engines": { - "node": ">=6" + "optionalDependencies": { + "@oxlint/binding-android-arm-eabi": "1.48.0", + "@oxlint/binding-android-arm64": "1.48.0", + "@oxlint/binding-darwin-arm64": "1.48.0", + "@oxlint/binding-darwin-x64": "1.48.0", + "@oxlint/binding-freebsd-x64": "1.48.0", + "@oxlint/binding-linux-arm-gnueabihf": "1.48.0", + "@oxlint/binding-linux-arm-musleabihf": "1.48.0", + "@oxlint/binding-linux-arm64-gnu": "1.48.0", + "@oxlint/binding-linux-arm64-musl": "1.48.0", + "@oxlint/binding-linux-ppc64-gnu": "1.48.0", + "@oxlint/binding-linux-riscv64-gnu": "1.48.0", + "@oxlint/binding-linux-riscv64-musl": "1.48.0", + "@oxlint/binding-linux-s390x-gnu": "1.48.0", + "@oxlint/binding-linux-x64-gnu": "1.48.0", + "@oxlint/binding-linux-x64-musl": "1.48.0", + "@oxlint/binding-openharmony-arm64": "1.48.0", + "@oxlint/binding-win32-arm64-msvc": "1.48.0", + "@oxlint/binding-win32-ia32-msvc": "1.48.0", + "@oxlint/binding-win32-x64-msvc": "1.48.0" + }, + "peerDependencies": { + "oxlint-tsgolint": ">=0.12.2" + }, + "peerDependenciesMeta": { + "oxlint-tsgolint": { + "optional": true + } } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/picocolors": { "version": "1.1.1", @@ -3510,42 +3203,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/prettier": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.8.1.tgz", - "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", - "dev": true, - "license": "MIT", - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/react": { "version": "19.2.4", "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", @@ -3617,16 +3274,6 @@ "react-dom": ">=18" } }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/rollup": { "version": "4.57.1", "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.57.1.tgz", @@ -3694,28 +3341,12 @@ "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", "license": "MIT" }, - "node_modules/shebang-command": { + "node_modules/siginfo": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "license": "ISC" }, "node_modules/sonner": { "version": "2.0.7", @@ -3737,31 +3368,19 @@ "node": ">=0.10.0" } }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "MIT" }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/std-env": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", + "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } + "license": "MIT" }, "node_modules/tailwindcss": { "version": "4.1.18", @@ -3784,6 +3403,23 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -3801,17 +3437,24 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/ts-api-utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.4.0.tgz", - "integrity": "sha512-3TaVTaAv2gTiMB35i3FiGJaRfwb3Pyn/j3m/bfAvGe8FB7CF6u+LMYqYlDh7reQf7UNvoTvdfAqHGmPGOSsPmA==", + "node_modules/tinypool": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-2.1.0.tgz", + "integrity": "sha512-Pugqs6M0m7Lv1I7FtxN4aoyToKg1C4tu+/381vH35y8oENM/Ai7f7C4StcoK4/+BSw9ebcS8jRiVrORFKCALLw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18.12" - }, - "peerDependencies": { - "typescript": ">=4.8.4" + "node": "^20.0.0 || >=22.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-3.0.3.tgz", + "integrity": "sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" } }, "node_modules/tslib": { @@ -3820,26 +3463,12 @@ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "license": "0BSD" }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "license": "MIT", - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, "node_modules/typescript": { "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3848,30 +3477,6 @@ "node": ">=14.17" } }, - "node_modules/typescript-eslint": { - "version": "8.54.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.54.0.tgz", - "integrity": "sha512-CKsJ+g53QpsNPqbzUsfKVgd3Lny4yKZ1pP4qN3jdMOg/sisIDLGyDMezycquXLE5JsEU0wp3dGNdzig0/fmSVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/eslint-plugin": "8.54.0", - "@typescript-eslint/parser": "8.54.0", - "@typescript-eslint/typescript-estree": "8.54.0", - "@typescript-eslint/utils": "8.54.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^8.57.0 || ^9.0.0", - "typescript": ">=4.8.4 <6.0.0" - } - }, "node_modules/undici-types": { "version": "7.16.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", @@ -3910,16 +3515,6 @@ "browserslist": ">= 4.21.0" } }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "punycode": "^2.1.0" - } - }, "node_modules/vite": { "version": "7.3.1", "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", @@ -3996,30 +3591,99 @@ } } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/vitest": { + "version": "4.0.18", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-4.0.18.tgz", + "integrity": "sha512-hOQuK7h0FGKgBAas7v0mSAsnvrIgAvWmRFjmzpJ7SwFHH3g1k2u37JtYwOwmEKhK6ZO3v9ggDBBm0La1LCK4uQ==", "dev": true, "license": "MIT", + "dependencies": { + "@vitest/expect": "4.0.18", + "@vitest/mocker": "4.0.18", + "@vitest/pretty-format": "4.0.18", + "@vitest/runner": "4.0.18", + "@vitest/snapshot": "4.0.18", + "@vitest/spy": "4.0.18", + "@vitest/utils": "4.0.18", + "es-module-lexer": "^1.7.0", + "expect-type": "^1.2.2", + "magic-string": "^0.30.21", + "obug": "^2.1.1", + "pathe": "^2.0.3", + "picomatch": "^4.0.3", + "std-env": "^3.10.0", + "tinybench": "^2.9.0", + "tinyexec": "^1.0.2", + "tinyglobby": "^0.2.15", + "tinyrainbow": "^3.0.3", + "vite": "^6.0.0 || ^7.0.0", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, "engines": { - "node": ">=0.10.0" + "node": "^20.0.0 || ^22.0.0 || >=24.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^20.0.0 || ^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "4.0.18", + "@vitest/browser-preview": "4.0.18", + "@vitest/browser-webdriverio": "4.0.18", + "@vitest/ui": "4.0.18", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@opentelemetry/api": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" } }, "node_modules/yallist": { @@ -4028,43 +3692,6 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true, "license": "ISC" - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "4.3.6", - "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", - "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", - "dev": true, - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-validation-error": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", - "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18.0.0" - }, - "peerDependencies": { - "zod": "^3.25.0 || ^4.0.0" - } } } } diff --git a/frontend/package.json b/frontend/package.json index e64fb30..438d952 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,35 +6,34 @@ "scripts": { "dev": "vite", "build": "tsc -b && vite build", - "lint": "eslint .", - "preview": "vite preview" + "lint": "oxlint src/", + "format": "oxfmt --write src/", + "format:check": "oxfmt --check src/", + "preview": "vite preview", + "test": "vitest run", + "test:watch": "vitest" }, "dependencies": { - "@dnd-kit/core": "^6.3.1", - "@dnd-kit/sortable": "^10.0.0", - "@dnd-kit/utilities": "^3.2.2", - "@tanstack/react-query": "^5.90.20", - "react": "^19.2.0", - "react-dom": "^19.2.0", - "react-router-dom": "^7.13.0", - "sonner": "^2.0.7" + "@dnd-kit/core": "6.3.1", + "@dnd-kit/sortable": "10.0.0", + "@dnd-kit/utilities": "3.2.2", + "@tanstack/react-query": "5.90.20", + "react": "19.2.4", + "react-dom": "19.2.4", + "react-router-dom": "7.13.0", + "sonner": "2.0.7" }, "devDependencies": { - "@eslint/js": "^9.39.1", - "@tailwindcss/vite": "^4.1.18", - "@types/node": "^24.10.1", - "@types/react": "^19.2.5", - "@types/react-dom": "^19.2.3", - "@vitejs/plugin-react": "^5.1.1", - "eslint": "^9.39.1", - "eslint-config-prettier": "^10.1.8", - "eslint-plugin-react-hooks": "^7.0.1", - "eslint-plugin-react-refresh": "^0.4.24", - "globals": "^16.5.0", - "prettier": "^3.8.1", - "tailwindcss": "^4.1.18", - "typescript": "~5.9.3", - "typescript-eslint": "^8.46.4", - "vite": "^7.2.4" + "@tailwindcss/vite": "4.1.18", + "@types/node": "24.10.10", + "@types/react": "19.2.11", + "@types/react-dom": "19.2.3", + "@vitejs/plugin-react": "5.1.3", + "oxfmt": "0.33.0", + "oxlint": "1.48.0", + "tailwindcss": "4.1.18", + "typescript": "5.9.3", + "vite": "7.3.1", + "vitest": "4.0.18" } } diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index ef8b805..bfa6900 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -42,18 +42,12 @@ function App() { } /> } /> } /> - } - /> + } /> } /> } /> } /> } /> - } - /> + } /> diff --git a/frontend/src/api/admin.ts b/frontend/src/api/admin.ts index a3bb289..84dac49 100644 --- a/frontend/src/api/admin.ts +++ b/frontend/src/api/admin.ts @@ -30,11 +30,9 @@ import type { import type { Genlocke } from '../types/game' // Games -export const createGame = (data: CreateGameInput) => - api.post('/games', data) +export const createGame = (data: CreateGameInput) => api.post('/games', data) -export const updateGame = (id: number, data: UpdateGameInput) => - api.put(`/games/${id}`, data) +export const updateGame = (id: number, data: UpdateGameInput) => api.put(`/games/${id}`, data) export const deleteGame = (id: number) => api.del(`/games/${id}`) @@ -42,11 +40,8 @@ export const deleteGame = (id: number) => api.del(`/games/${id}`) export const createRoute = (gameId: number, data: CreateRouteInput) => api.post(`/games/${gameId}/routes`, data) -export const updateRoute = ( - gameId: number, - routeId: number, - data: UpdateRouteInput -) => api.put(`/games/${gameId}/routes/${routeId}`, data) +export const updateRoute = (gameId: number, routeId: number, data: UpdateRouteInput) => + api.put(`/games/${gameId}/routes/${routeId}`, data) export const deleteRoute = (gameId: number, routeId: number) => api.del(`/games/${gameId}/routes/${routeId}`) @@ -55,12 +50,7 @@ export const reorderRoutes = (gameId: number, routes: RouteReorderItem[]) => api.put(`/games/${gameId}/routes/reorder`, { routes }) // Pokemon -export const listPokemon = ( - search?: string, - limit = 50, - offset = 0, - type?: string -) => { +export const listPokemon = (search?: string, limit = 50, offset = 0, type?: string) => { const params = new URLSearchParams() if (search) params.set('search', search) if (type) params.set('type', type) @@ -69,8 +59,7 @@ export const listPokemon = ( return api.get(`/pokemon?${params}`) } -export const createPokemon = (data: CreatePokemonInput) => - api.post('/pokemon', data) +export const createPokemon = (data: CreatePokemonInput) => api.post('/pokemon', data) export const updatePokemon = (id: number, data: UpdatePokemonInput) => api.put(`/pokemon/${id}`, data) @@ -97,12 +86,7 @@ export const bulkImportBosses = (gameId: number, items: unknown[]) => api.post(`/games/${gameId}/bosses/bulk-import`, items) // Evolutions -export const listEvolutions = ( - search?: string, - limit = 50, - offset = 0, - trigger?: string -) => { +export const listEvolutions = (search?: string, limit = 50, offset = 0, trigger?: string) => { const params = new URLSearchParams() if (search) params.set('search', search) if (trigger) params.set('trigger', trigger) @@ -120,8 +104,7 @@ export const updateEvolution = (id: number, data: UpdateEvolutionInput) => export const deleteEvolution = (id: number) => api.del(`/evolutions/${id}`) // Export -export const exportGames = () => - api.get[]>('/export/games') +export const exportGames = () => api.get[]>('/export/games') export const exportGameRoutes = (gameId: number) => api.get<{ filename: string; data: unknown }>(`/export/games/${gameId}/routes`) @@ -129,27 +112,19 @@ export const exportGameRoutes = (gameId: number) => export const exportGameBosses = (gameId: number) => api.get<{ filename: string; data: unknown }>(`/export/games/${gameId}/bosses`) -export const exportPokemon = () => - api.get[]>('/export/pokemon') +export const exportPokemon = () => api.get[]>('/export/pokemon') -export const exportEvolutions = () => - api.get[]>('/export/evolutions') +export const exportEvolutions = () => api.get[]>('/export/evolutions') // Route Encounters -export const addRouteEncounter = ( - routeId: number, - data: CreateRouteEncounterInput -) => api.post(`/routes/${routeId}/pokemon`, data) +export const addRouteEncounter = (routeId: number, data: CreateRouteEncounterInput) => + api.post(`/routes/${routeId}/pokemon`, data) export const updateRouteEncounter = ( routeId: number, encounterId: number, data: UpdateRouteEncounterInput -) => - api.put( - `/routes/${routeId}/pokemon/${encounterId}`, - data - ) +) => api.put(`/routes/${routeId}/pokemon/${encounterId}`, data) export const removeRouteEncounter = (routeId: number, encounterId: number) => api.del(`/routes/${routeId}/pokemon/${encounterId}`) @@ -158,11 +133,8 @@ export const removeRouteEncounter = (routeId: number, encounterId: number) => export const createBossBattle = (gameId: number, data: CreateBossBattleInput) => api.post(`/games/${gameId}/bosses`, data) -export const updateBossBattle = ( - gameId: number, - bossId: number, - data: UpdateBossBattleInput -) => api.put(`/games/${gameId}/bosses/${bossId}`, data) +export const updateBossBattle = (gameId: number, bossId: number, data: UpdateBossBattleInput) => + api.put(`/games/${gameId}/bosses/${bossId}`, data) export const deleteBossBattle = (gameId: number, bossId: number) => api.del(`/games/${gameId}/bosses/${bossId}`) @@ -170,11 +142,8 @@ export const deleteBossBattle = (gameId: number, bossId: number) => export const reorderBosses = (gameId: number, bosses: BossReorderItem[]) => api.put(`/games/${gameId}/bosses/reorder`, { bosses }) -export const setBossTeam = ( - gameId: number, - bossId: number, - team: BossPokemonInput[] -) => api.put(`/games/${gameId}/bosses/${bossId}/pokemon`, team) +export const setBossTeam = (gameId: number, bossId: number, team: BossPokemonInput[]) => + api.put(`/games/${gameId}/bosses/${bossId}/pokemon`, team) // Genlockes export const updateGenlocke = (id: number, data: UpdateGenlockeInput) => diff --git a/frontend/src/api/bosses.ts b/frontend/src/api/bosses.ts index 0960fc3..c212ea9 100644 --- a/frontend/src/api/bosses.ts +++ b/frontend/src/api/bosses.ts @@ -1,14 +1,7 @@ import { api } from './client' -import type { - BossBattle, - BossResult, - CreateBossResultInput, -} from '../types/game' +import type { BossBattle, BossResult, CreateBossResultInput } from '../types/game' -export function getGameBosses( - gameId: number, - all?: boolean -): Promise { +export function getGameBosses(gameId: number, all?: boolean): Promise { const params = all ? '?all=true' : '' return api.get(`/games/${gameId}/bosses${params}`) } @@ -17,16 +10,10 @@ export function getBossResults(runId: number): Promise { return api.get(`/runs/${runId}/boss-results`) } -export function createBossResult( - runId: number, - data: CreateBossResultInput -): Promise { +export function createBossResult(runId: number, data: CreateBossResultInput): Promise { return api.post(`/runs/${runId}/boss-results`, data) } -export function deleteBossResult( - runId: number, - resultId: number -): Promise { +export function deleteBossResult(runId: number, resultId: number): Promise { return api.del(`/runs/${runId}/boss-results/${resultId}`) } diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index ec6424b..9974ad2 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1,4 +1,4 @@ -const API_BASE = import.meta.env.VITE_API_URL ?? '' +const API_BASE = import.meta.env['VITE_API_URL'] ?? '' export class ApiError extends Error { status: number diff --git a/frontend/src/api/encounters.ts b/frontend/src/api/encounters.ts index 3ffffda..5da8a6f 100644 --- a/frontend/src/api/encounters.ts +++ b/frontend/src/api/encounters.ts @@ -14,10 +14,7 @@ export function createEncounter( return api.post(`/runs/${runId}/encounters`, data) } -export function updateEncounter( - id: number, - data: UpdateEncounterInput -): Promise { +export function updateEncounter(id: number, data: UpdateEncounterInput): Promise { return api.patch(`/encounters/${id}`, data) } @@ -25,10 +22,7 @@ export function deleteEncounter(id: number): Promise { return api.del(`/encounters/${id}`) } -export function fetchEvolutions( - pokemonId: number, - region?: string -): Promise { +export function fetchEvolutions(pokemonId: number, region?: string): Promise { const params = region ? `?region=${encodeURIComponent(region)}` : '' return api.get(`/pokemon/${pokemonId}/evolutions${params}`) } diff --git a/frontend/src/api/games.ts b/frontend/src/api/games.ts index f1394ef..a092816 100644 --- a/frontend/src/api/games.ts +++ b/frontend/src/api/games.ts @@ -19,10 +19,7 @@ export function getGameRoutes(gameId: number): Promise { return api.get(`/games/${gameId}/routes?flat=true`) } -export function getRoutePokemon( - routeId: number, - gameId?: number -): Promise { +export function getRoutePokemon(routeId: number, gameId?: number): Promise { const params = gameId != null ? `?game_id=${gameId}` : '' return api.get(`/routes/${routeId}/pokemon${params}`) } diff --git a/frontend/src/api/genlockes.ts b/frontend/src/api/genlockes.ts index be5c42b..0885340 100644 --- a/frontend/src/api/genlockes.ts +++ b/frontend/src/api/genlockes.ts @@ -47,8 +47,5 @@ export function advanceLeg( legOrder: number, data?: AdvanceLegInput ): Promise { - return api.post( - `/genlockes/${genlockeId}/legs/${legOrder}/advance`, - data ?? {} - ) + return api.post(`/genlockes/${genlockeId}/legs/${legOrder}/advance`, data ?? {}) } diff --git a/frontend/src/api/pokemon.ts b/frontend/src/api/pokemon.ts index 17f85fb..04defb9 100644 --- a/frontend/src/api/pokemon.ts +++ b/frontend/src/api/pokemon.ts @@ -16,8 +16,6 @@ export function fetchPokemonEncounterLocations( return api.get(`/pokemon/${pokemonId}/encounter-locations`) } -export function fetchPokemonEvolutionChain( - pokemonId: number -): Promise { +export function fetchPokemonEvolutionChain(pokemonId: number): Promise { return api.get(`/pokemon/${pokemonId}/evolution-chain`) } diff --git a/frontend/src/api/runs.ts b/frontend/src/api/runs.ts index 1dbe336..8c67e74 100644 --- a/frontend/src/api/runs.ts +++ b/frontend/src/api/runs.ts @@ -1,10 +1,5 @@ import { api } from './client' -import type { - NuzlockeRun, - RunDetail, - CreateRunInput, - UpdateRunInput, -} from '../types/game' +import type { NuzlockeRun, RunDetail, CreateRunInput, UpdateRunInput } from '../types/game' export function getRuns(): Promise { return api.get('/runs') @@ -18,10 +13,7 @@ export function createRun(data: CreateRunInput): Promise { return api.post('/runs', data) } -export function updateRun( - id: number, - data: UpdateRunInput -): Promise { +export function updateRun(id: number, data: UpdateRunInput): Promise { return api.patch(`/runs/${id}`, data) } diff --git a/frontend/src/components/BossDefeatModal.tsx b/frontend/src/components/BossDefeatModal.tsx index e53bf84..6765d41 100644 --- a/frontend/src/components/BossDefeatModal.tsx +++ b/frontend/src/components/BossDefeatModal.tsx @@ -10,14 +10,11 @@ interface BossDefeatModalProps { starterName?: string | null } -function matchVariant( - labels: string[], - starterName?: string | null -): string | null { +function matchVariant(labels: string[], starterName?: string | null): string | null { if (!starterName || labels.length === 0) return null const lower = starterName.toLowerCase() const matches = labels.filter((l) => l.toLowerCase().includes(lower)) - return matches.length === 1 ? matches[0] : null + return matches.length === 1 ? (matches[0] ?? null) : null } export function BossDefeatModal({ @@ -46,14 +43,13 @@ export function BossDefeatModal({ ) const showPills = hasVariants && autoMatch === null const [selectedVariant, setSelectedVariant] = useState( - autoMatch ?? (hasVariants ? variantLabels[0] : null) + autoMatch ?? (hasVariants ? (variantLabels[0] ?? null) : null) ) const displayedPokemon = useMemo(() => { if (!hasVariants) return boss.pokemon return boss.pokemon.filter( - (bp) => - bp.conditionLabel === selectedVariant || bp.conditionLabel === null + (bp) => bp.conditionLabel === selectedVariant || bp.conditionLabel === null ) }, [boss.pokemon, hasVariants, selectedVariant]) @@ -72,9 +68,7 @@ export function BossDefeatModal({

Battle: {boss.name}

-

- {boss.location} -

+

{boss.location}

{/* Boss team preview */} @@ -104,11 +98,7 @@ export function BossDefeatModal({ .map((bp) => (
{bp.pokemon.spriteUrl ? ( - {bp.pokemon.name} + {bp.pokemon.name} ) : (
)} @@ -158,9 +148,7 @@ export function BossDefeatModal({ {!hardcoreMode && (
- + void onClose: () => void @@ -87,12 +87,7 @@ export function EggEncounterModal({ onClick={onClose} className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200" > - + ) : (
- {selectedPokemon.name[0].toUpperCase()} + {selectedPokemon.name[0]?.toUpperCase()}
)} @@ -183,14 +178,10 @@ export function EggEncounterModal({ className="flex flex-col items-center p-2 rounded-lg border border-gray-200 dark:border-gray-700 hover:border-green-400 dark:hover:border-green-600 text-center transition-colors" > {p.spriteUrl ? ( - {p.name} + {p.name} ) : (
- {p.name[0].toUpperCase()} + {p.name[0]?.toUpperCase()}
)} @@ -200,13 +191,9 @@ export function EggEncounterModal({ ))}
)} - {search.length >= 2 && - !isSearching && - searchResults.length === 0 && ( -

- No pokemon found -

- )} + {search.length >= 2 && !isSearching && searchResults.length === 0 && ( +

No pokemon found

+ )} )}
diff --git a/frontend/src/components/EncounterMethodBadge.tsx b/frontend/src/components/EncounterMethodBadge.tsx index f436e33..44986d4 100644 --- a/frontend/src/components/EncounterMethodBadge.tsx +++ b/frontend/src/components/EncounterMethodBadge.tsx @@ -1,8 +1,7 @@ export const METHOD_CONFIG: Record = { starter: { label: 'Starter', - color: - 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300', + color: 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/40 dark:text-yellow-300', }, gift: { label: 'Gift', @@ -10,18 +9,15 @@ export const METHOD_CONFIG: Record = { }, fossil: { label: 'Fossil', - color: - 'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300', + color: 'bg-amber-100 text-amber-800 dark:bg-amber-900/40 dark:text-amber-300', }, trade: { label: 'Trade', - color: - 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300', + color: 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/40 dark:text-emerald-300', }, walk: { label: 'Grass', - color: - 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300', + color: 'bg-green-100 text-green-800 dark:bg-green-900/40 dark:text-green-300', }, headbutt: { label: 'Headbutt', @@ -33,8 +29,7 @@ export const METHOD_CONFIG: Record = { }, 'rock-smash': { label: 'Rock Smash', - color: - 'bg-orange-100 text-orange-800 dark:bg-orange-900/40 dark:text-orange-300', + color: 'bg-orange-100 text-orange-800 dark:bg-orange-900/40 dark:text-orange-300', }, 'old-rod': { label: 'Old Rod', @@ -46,8 +41,7 @@ export const METHOD_CONFIG: Record = { }, 'super-rod': { label: 'Super Rod', - color: - 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900/40 dark:text-indigo-300', + color: 'bg-indigo-100 text-indigo-800 dark:bg-indigo-900/40 dark:text-indigo-300', }, } @@ -75,8 +69,7 @@ export function getMethodLabel(method: string): string { export function getMethodColor(method: string): string { return ( - METHOD_CONFIG[method]?.color ?? - 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300' + METHOD_CONFIG[method]?.color ?? 'bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-300' ) } @@ -89,12 +82,9 @@ export function EncounterMethodBadge({ }) { const config = METHOD_CONFIG[method] if (!config) return null - const sizeClass = - size === 'xs' ? 'text-[8px] px-1 py-0' : 'text-[9px] px-1.5 py-0.5' + const sizeClass = size === 'xs' ? 'text-[8px] px-1 py-0' : 'text-[9px] px-1.5 py-0.5' return ( - + {config.label} ) diff --git a/frontend/src/components/EncounterModal.tsx b/frontend/src/components/EncounterModal.tsx index f487837..d860c4d 100644 --- a/frontend/src/components/EncounterModal.tsx +++ b/frontend/src/components/EncounterModal.tsx @@ -1,43 +1,36 @@ import { useState, useEffect, useMemo } from 'react' import { useRoutePokemon } from '../hooks/useGames' import { useNameSuggestions } from '../hooks/useRuns' -import { - EncounterMethodBadge, - getMethodLabel, - METHOD_ORDER, -} from './EncounterMethodBadge' -import type { - Route, - EncounterDetail, - EncounterStatus, - RouteEncounterDetail, -} from '../types' +import { EncounterMethodBadge, getMethodLabel, METHOD_ORDER } from './EncounterMethodBadge' +import type { Route, EncounterDetail, EncounterStatus, RouteEncounterDetail } from '../types' interface EncounterModalProps { route: Route gameId: number runId: number - namingScheme?: string | null - isGenlocke?: boolean - existing?: EncounterDetail - dupedPokemonIds?: Set - retiredPokemonIds?: Set + namingScheme?: string | null | undefined + isGenlocke?: boolean | undefined + existing?: EncounterDetail | undefined + dupedPokemonIds?: Set | undefined + retiredPokemonIds?: Set | undefined onSubmit: (data: { routeId: number pokemonId: number - nickname?: string + nickname?: string | undefined status: EncounterStatus - catchLevel?: number - }) => void - onUpdate?: (data: { - id: number - data: { - nickname?: string - status?: EncounterStatus - faintLevel?: number - deathCause?: string - } + catchLevel?: number | undefined }) => void + onUpdate?: + | ((data: { + id: number + data: { + nickname?: string | undefined + status?: EncounterStatus | undefined + faintLevel?: number | undefined + deathCause?: string | undefined + } + }) => void) + | undefined onClose: () => void isPending: boolean } @@ -91,11 +84,9 @@ function pickRandomPokemon( pokemon: RouteEncounterDetail[], dupedIds?: Set ): RouteEncounterDetail | null { - const eligible = dupedIds - ? pokemon.filter((rp) => !dupedIds.has(rp.pokemonId)) - : pokemon + const eligible = dupedIds ? pokemon.filter((rp) => !dupedIds.has(rp.pokemonId)) : pokemon if (eligible.length === 0) return null - return eligible[Math.floor(Math.random() * eligible.length)] + return eligible[Math.floor(Math.random() * eligible.length)] ?? null } export function EncounterModal({ @@ -112,20 +103,12 @@ export function EncounterModal({ onClose, isPending, }: EncounterModalProps) { - const { data: routePokemon, isLoading: loadingPokemon } = useRoutePokemon( - route.id, - gameId - ) + const { data: routePokemon, isLoading: loadingPokemon } = useRoutePokemon(route.id, gameId) - const [selectedPokemon, setSelectedPokemon] = - useState(null) - const [status, setStatus] = useState( - existing?.status ?? 'caught' - ) + const [selectedPokemon, setSelectedPokemon] = useState(null) + const [status, setStatus] = useState(existing?.status ?? 'caught') const [nickname, setNickname] = useState(existing?.nickname ?? '') - const [catchLevel, setCatchLevel] = useState( - existing?.catchLevel?.toString() ?? '' - ) + const [catchLevel, setCatchLevel] = useState(existing?.catchLevel?.toString() ?? '') const [faintLevel, setFaintLevel] = useState('') const [deathCause, setDeathCause] = useState('') const [search, setSearch] = useState('') @@ -133,8 +116,7 @@ export function EncounterModal({ const isEditing = !!existing const showSuggestions = !!namingScheme && status === 'caught' && !isEditing - const lineagePokemonId = - isGenlocke && selectedPokemon ? selectedPokemon.pokemonId : null + const lineagePokemonId = isGenlocke && selectedPokemon ? selectedPokemon.pokemonId : null const { data: suggestions, refetch: regenerate, @@ -144,9 +126,7 @@ export function EncounterModal({ // Pre-select pokemon when editing useEffect(() => { if (existing && routePokemon) { - const match = routePokemon.find( - (rp) => rp.pokemonId === existing.pokemonId - ) + const match = routePokemon.find((rp) => rp.pokemonId === existing.pokemonId) if (match) setSelectedPokemon(match) } }, [existing, routePokemon]) @@ -198,12 +178,7 @@ export function EncounterModal({ onClick={onClose} className="text-gray-400 hover:text-gray-600 dark:hover:text-gray-200" > - +
-

- {route.name} -

+

{route.name}

@@ -233,16 +206,12 @@ export function EncounterModal({ loadingPokemon || !routePokemon || (dupedPokemonIds - ? routePokemon.every((rp) => - dupedPokemonIds.has(rp.pokemonId) - ) + ? routePokemon.every((rp) => dupedPokemonIds.has(rp.pokemonId)) : false) } onClick={() => { if (routePokemon) { - setSelectedPokemon( - pickRandomPokemon(routePokemon, dupedPokemonIds) - ) + setSelectedPokemon(pickRandomPokemon(routePokemon, dupedPokemonIds)) } }} className="px-2.5 py-1 text-xs font-medium rounded-lg border border-purple-300 dark:border-purple-600 text-purple-600 dark:text-purple-400 hover:bg-purple-50 dark:hover:bg-purple-900/20 disabled:opacity-40 disabled:cursor-not-allowed transition-colors" @@ -279,15 +248,12 @@ export function EncounterModal({ )}
{pokemon.map((rp) => { - const isDuped = - dupedPokemonIds?.has(rp.pokemonId) ?? false + const isDuped = dupedPokemonIds?.has(rp.pokemonId) ?? false return ( @@ -360,7 +320,7 @@ export function EncounterModal({ /> ) : (
- {existing.pokemon.name[0].toUpperCase()} + {existing.pokemon.name[0]?.toUpperCase()}
)}
@@ -477,53 +437,45 @@ export function EncounterModal({ )} {/* Faint Level + Death Cause (only when editing a caught pokemon to mark dead) */} - {isEditing && - existing?.status === 'caught' && - existing?.faintLevel === null && ( - <> -
- - setFaintLevel(e.target.value)} - placeholder="Leave empty if still alive" - className="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500" - /> -
-
- - setDeathCause(e.target.value)} - placeholder="e.g. Crit from rival's Charizard" - className="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500" - /> -
- - )} + {isEditing && existing?.status === 'caught' && existing?.faintLevel === null && ( + <> +
+ + setFaintLevel(e.target.value)} + placeholder="Leave empty if still alive" + className="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+
+ + setDeathCause(e.target.value)} + placeholder="e.g. Crit from rival's Charizard" + className="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-blue-500" + /> +
+ + )}
diff --git a/frontend/src/components/EndRunModal.tsx b/frontend/src/components/EndRunModal.tsx index 4dc79eb..2059e94 100644 --- a/frontend/src/components/EndRunModal.tsx +++ b/frontend/src/components/EndRunModal.tsx @@ -7,12 +7,7 @@ interface EndRunModalProps { genlockeContext?: RunGenlockeContext | null } -export function EndRunModal({ - onConfirm, - onClose, - isPending, - genlockeContext, -}: EndRunModalProps) { +export function EndRunModal({ onConfirm, onClose, isPending, genlockeContext }: EndRunModalProps) { const victoryDescription = genlockeContext ? genlockeContext.isFinalLeg ? 'Complete the final leg of your genlocke!' @@ -31,9 +26,7 @@ export function EndRunModal({

End Run

-

- How did your run end? -

+

How did your run end?

) : ( -
+
{game.name.replace('Pokemon ', '')}
)}
-

- {game.name} -

+

{game.name}

{game.region.charAt(0).toUpperCase() + game.region.slice(1)} {game.releaseYear && ( - - {game.releaseYear} - + {game.releaseYear} )}
@@ -65,11 +58,7 @@ export function GameCard({ game, selected, onSelect }: GameCardProps) { stroke="currentColor" strokeWidth={3} > - +
)} diff --git a/frontend/src/components/GameGrid.tsx b/frontend/src/components/GameGrid.tsx index 75f81f5..35056f9 100644 --- a/frontend/src/components/GameGrid.tsx +++ b/frontend/src/components/GameGrid.tsx @@ -18,7 +18,7 @@ interface GameGridProps { games: Game[] selectedId: number | null onSelect: (game: Game) => void - runs?: NuzlockeRun[] + runs?: NuzlockeRun[] | undefined } export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) { @@ -27,38 +27,26 @@ export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) { const [hideWithActiveRun, setHideWithActiveRun] = useState(false) const [hideCompleted, setHideCompleted] = useState(false) - const generations = useMemo( - () => [...new Set(games.map((g) => g.generation))].sort(), - [games] - ) + const generations = useMemo(() => [...new Set(games.map((g) => g.generation))].sort(), [games]) - const regions = useMemo( - () => [...new Set(games.map((g) => g.region))].sort(), - [games] - ) + const regions = useMemo(() => [...new Set(games.map((g) => g.region))].sort(), [games]) const activeRunGameIds = useMemo(() => { if (!runs) return new Set() - return new Set( - runs.filter((r) => r.status === 'active').map((r) => r.gameId) - ) + return new Set(runs.filter((r) => r.status === 'active').map((r) => r.gameId)) }, [runs]) const completedRunGameIds = useMemo(() => { if (!runs) return new Set() - return new Set( - runs.filter((r) => r.status === 'completed').map((r) => r.gameId) - ) + return new Set(runs.filter((r) => r.status === 'completed').map((r) => r.gameId)) }, [runs]) const filtered = useMemo(() => { let result = games if (filter) result = result.filter((g) => g.generation === filter) if (regionFilter) result = result.filter((g) => g.region === regionFilter) - if (hideWithActiveRun) - result = result.filter((g) => !activeRunGameIds.has(g.id)) - if (hideCompleted) - result = result.filter((g) => !completedRunGameIds.has(g.id)) + if (hideWithActiveRun) result = result.filter((g) => !activeRunGameIds.has(g.id)) + if (hideCompleted) result = result.filter((g) => !completedRunGameIds.has(g.id)) return result }, [ games, @@ -91,9 +79,7 @@ export function GameGrid({ games, selectedId, onSelect, runs }: GameGridProps) {
- - Gen: - + Gen:
- - Region: - + Region:
{entry.nickname && ( -
- {displayPokemon.name} -
+
{displayPokemon.name}
)}
@@ -50,9 +48,7 @@ function GraveyardCard({ entry }: { entry: GraveyardEntry }) { Lv. {entry.catchLevel} → {entry.faintLevel}
-
- {entry.routeName} -
+
{entry.routeName}
Leg {entry.legOrder} — {entry.gameName} @@ -134,8 +130,8 @@ export function GenlockeGraveyard({ genlockeId }: GenlockeGraveyardProps) { {data.deadliestLeg && ( - Deadliest: Leg {data.deadliestLeg.legOrder} —{' '} - {data.deadliestLeg.gameName} ({data.deadliestLeg.deathCount}) + Deadliest: Leg {data.deadliestLeg.legOrder} — {data.deadliestLeg.gameName} ( + {data.deadliestLeg.deathCount}) )}
@@ -144,9 +140,7 @@ export function GenlockeGraveyard({ genlockeId }: GenlockeGraveyardProps) {
applyEvolution(true)} className="flex-1 px-4 py-2 bg-amber-600 text-white rounded-lg font-medium hover:bg-amber-700 disabled:opacity-50 disabled:cursor-not-allowed transition-colors" > - {isPending - ? 'Saving...' - : `Add ${shedCompanion.toPokemon.name}`} + {isPending ? 'Saving...' : `Add ${shedCompanion.toPokemon.name}`}
@@ -400,14 +361,10 @@ export function StatusChangeModal({ className="w-full flex items-center gap-3 p-3 rounded-lg border border-gray-200 dark:border-gray-600 hover:bg-purple-50 dark:hover:bg-purple-900/20 hover:border-purple-300 dark:hover:border-purple-600 transition-colors disabled:opacity-50" > {form.spriteUrl ? ( - {form.name} + {form.name} ) : (
- {form.name[0].toUpperCase()} + {form.name[0]?.toUpperCase()}
)}
@@ -441,8 +398,7 @@ export function StatusChangeModal({ htmlFor="death-level" className="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1" > - Level at Death{' '} - (optional) + Level at Death (optional) - Cause of Death{' '} - (optional) + Cause of Death (optional) ) })} diff --git a/frontend/src/components/TypeBadge.tsx b/frontend/src/components/TypeBadge.tsx index 52450e8..3250486 100644 --- a/frontend/src/components/TypeBadge.tsx +++ b/frontend/src/components/TypeBadge.tsx @@ -5,7 +5,5 @@ interface TypeBadgeProps { export function TypeBadge({ type, size = 'sm' }: TypeBadgeProps) { const height = size === 'md' ? 'h-5' : 'h-4' - return ( - {type} - ) + return {type} } diff --git a/frontend/src/components/admin/AdminTable.tsx b/frontend/src/components/admin/AdminTable.tsx index bdce169..34d44a8 100644 --- a/frontend/src/components/admin/AdminTable.tsx +++ b/frontend/src/components/admin/AdminTable.tsx @@ -79,10 +79,7 @@ export function AdminTable({ {Array.from({ length: 5 }).map((_, i) => ( {columns.map((col) => ( - +
))} @@ -114,9 +111,7 @@ export function AdminTable({ return ( handleSort(col.header) : undefined - } + onClick={sortable ? () => handleSort(col.header) : undefined} className={`px-4 py-3 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider ${col.className ?? ''} ${sortable ? 'cursor-pointer select-none hover:text-gray-700 dark:hover:text-gray-200' : ''}`} > @@ -138,9 +133,7 @@ export function AdminTable({ key={keyFn(row)} onClick={onRowClick ? () => onRowClick(row) : undefined} className={ - onRowClick - ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800' - : '' + onRowClick ? 'cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800' : '' } > {columns.map((col) => ( diff --git a/frontend/src/components/admin/BossBattleFormModal.tsx b/frontend/src/components/admin/BossBattleFormModal.tsx index 20a11a2..91729f9 100644 --- a/frontend/src/components/admin/BossBattleFormModal.tsx +++ b/frontend/src/components/admin/BossBattleFormModal.tsx @@ -1,10 +1,7 @@ import { type FormEvent, useState } from 'react' import { FormModal } from './FormModal' import type { BossBattle, Game, Route } from '../../types/game' -import type { - CreateBossBattleInput, - UpdateBossBattleInput, -} from '../../types/admin' +import type { CreateBossBattleInput, UpdateBossBattleInput } from '../../types/admin' interface BossBattleFormModalProps { boss?: BossBattle @@ -70,9 +67,7 @@ export function BossBattleFormModal({ const [badgeImageUrl, setBadgeImageUrl] = useState(boss?.badgeImageUrl ?? '') const [levelCap, setLevelCap] = useState(String(boss?.levelCap ?? '')) const [order, setOrder] = useState(String(boss?.order ?? nextOrder)) - const [afterRouteId, setAfterRouteId] = useState( - String(boss?.afterRouteId ?? '') - ) + const [afterRouteId, setAfterRouteId] = useState(String(boss?.afterRouteId ?? '')) const [location, setLocation] = useState(boss?.location ?? '') const [section, setSection] = useState(boss?.section ?? '') const [spriteUrl, setSpriteUrl] = useState(boss?.spriteUrl ?? '') @@ -212,9 +207,7 @@ export function BossBattleFormModal({
{games && games.length > 1 && (
- + setAfterRouteId(e.target.value)} @@ -261,9 +252,7 @@ export function BossBattleFormModal({ />
- + - (a[0] ?? '').localeCompare(b[0] ?? '') - ) + const remaining = [...map.entries()].sort((a, b) => (a[0] ?? '').localeCompare(b[0] ?? '')) for (const [label, pokemon] of remaining) { variants.push({ label, pokemon }) } return variants } -export function BossTeamEditor({ - boss, - onSave, - onClose, - isSaving, -}: BossTeamEditorProps) { - const [variants, setVariants] = useState(() => - groupByVariant(boss) - ) +export function BossTeamEditor({ boss, onSave, onClose, isSaving }: BossTeamEditorProps) { + const [variants, setVariants] = useState(() => groupByVariant(boss)) const [activeTab, setActiveTab] = useState(0) const [newVariantName, setNewVariantName] = useState('') const [showAddVariant, setShowAddVariant] = useState(false) const activeVariant = variants[activeTab] ?? variants[0] - const updateVariant = ( - tabIndex: number, - updater: (v: Variant) => Variant - ) => { + const updateVariant = (tabIndex: number, updater: (v: Variant) => Variant) => { setVariants((prev) => prev.map((v, i) => (i === tabIndex ? updater(v) : v))) } @@ -108,16 +96,10 @@ export function BossTeamEditor({ })) } - const updateSlot = ( - index: number, - field: string, - value: number | string | null - ) => { + const updateSlot = (index: number, field: string, value: number | string | null) => { updateVariant(activeTab, (v) => ({ ...v, - pokemon: v.pokemon.map((item, i) => - i === index ? { ...item, [field]: value } : item - ), + pokemon: v.pokemon.map((item, i) => (i === index ? { ...item, [field]: value } : item)), })) } @@ -138,8 +120,9 @@ export function BossTeamEditor({ } const removeVariant = (tabIndex: number) => { - if (variants[tabIndex].label === null) return - if (!window.confirm(`Remove variant "${variants[tabIndex].label}"?`)) return + const variant = variants[tabIndex] + if (!variant || variant.label === null) return + if (!window.confirm(`Remove variant "${variant.label}"?`)) return setVariants((prev) => prev.filter((_, i) => i !== tabIndex)) setActiveTab((prev) => Math.min(prev, variants.length - 2)) } @@ -148,15 +131,14 @@ export function BossTeamEditor({ e.preventDefault() const allPokemon: BossPokemonInput[] = [] for (const variant of variants) { - const conditionLabel = - variants.length === 1 && variant.label === null ? null : variant.label - const validPokemon = variant.pokemon.filter( - (t) => t.pokemonId != null && t.level - ) + const conditionLabel = variants.length === 1 && variant.label === null ? null : variant.label + const validPokemon = variant.pokemon.filter((t) => t.pokemonId != null && t.level) for (let i = 0; i < validPokemon.length; i++) { + const p = validPokemon[i] + if (!p?.pokemonId) continue allPokemon.push({ - pokemonId: validPokemon[i].pokemonId!, - level: Number(validPokemon[i].level), + pokemonId: p.pokemonId, + level: Number(p.level), order: i + 1, conditionLabel, }) @@ -247,11 +229,8 @@ export function BossTeamEditor({
- {activeVariant.pokemon.map((slot, index) => ( -
+ {activeVariant?.pokemon.map((slot, index) => ( +
- + ))} - {activeVariant.pokemon.length < 6 && ( + {activeVariant && activeVariant.pokemon.length < 6 && (