From 1e5b79dac6c1bf336e0d3263514162931149cb27 Mon Sep 17 00:00:00 2001 From: Haozhe Wu Date: Tue, 28 Jul 2026 14:36:49 +0800 Subject: [PATCH] chore(frontend): move to Node 22 and React Router 8 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit React Router 7.12.0 through 8.2.x carry a high-severity RSC-mode CSRF bypass (GHSA-qwww-vcr4-c8h2). We were on 7.18.1, inside that range. The advisory is not reachable here — the app is a client-side SPA on createBrowserRouter with no @react-router/server and no RSC entry point, and the frontend ships as static Vite output — but 7.18.1 is the final 7.x release, no backport exists, and 8.3.0 is the only patched version, so staying put means staying on an EOL line with a permanent open alert. react-router-dom has no 8.x at all; the DOM exports moved into react-router itself. So the dependency is swapped and every import rewritten. All ten APIs in use here are unchanged in 8.3.0, and none of the data-layer surface that changed most between majors is used. react-router 8 requires Node >=22.22.0, which is the same wall that had jsdom 30 and @testing-library/jest-dom 7 sitting in the Dependabot ignore list. Node 20 reached EOL on 2026-04-30, so the toolchain moves to Node 22 across CI, the wiki workflow, the Dockerfile and docker-compose. That unblocks all three at once: jsdom and jest-dom are taken here too, and their ignores are removed rather than left carrying a rationale that no longer holds. Verified on the frontend suite: tsc -b and vite build clean, 310 tests across 35 files pass before and after the jsdom/jest-dom bumps. --- .github/dependabot.yml | 20 +- .github/workflows/test.yml | 2 +- .github/workflows/wiki.yml | 2 +- Dockerfile | 4 +- docker-compose.yml | 2 +- frontend/package-lock.json | 212 +++++++++--------- frontend/package.json | 6 +- .../src/components/chat/RunCompleteCard.tsx | 2 +- frontend/src/components/layout/Layout.tsx | 2 +- frontend/src/main.tsx | 2 +- frontend/src/pages/Agent.tsx | 2 +- frontend/src/pages/AlphaZoo.tsx | 2 +- frontend/src/pages/Home.tsx | 2 +- frontend/src/pages/Reports.tsx | 2 +- frontend/src/pages/RunDetail.tsx | 2 +- frontend/src/pages/__tests__/Reports.test.tsx | 2 +- .../src/pages/__tests__/RunDetail.test.tsx | 2 +- frontend/src/router.tsx | 2 +- frontend/vite.config.ts | 2 +- 19 files changed, 130 insertions(+), 142 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 99a15be2..ba69cdcd 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -83,19 +83,17 @@ updates: applies-to: version-updates update-types: ["minor", "patch"] ignore: - # Both majors are blocked on infrastructure migrations we have not done, - # so they can only sit red. Same rationale as the pandas pin above: - # revisit each as a dedicated migration, not a dependency bump. - # @vitejs/plugin-react 6.x peers vite@^8 (we are on vite 6.x). - # @testing-library/jest-dom 7.x requires Node >=22 (CI/Docker use 20). - # jsdom 30.x requires Node ^22.22.2 || ^24.15.0 || >=26 (same wall); - # on Node 20 it surfaces as vitest failing to start its pool workers. + # @vitejs/plugin-react 6.x peers vite@^8 and we are on vite 6.x, so it can + # only sit red. Same rationale as the pandas pin above: revisit as a + # dedicated migration, not a dependency bump. + # + # The jsdom and @testing-library/jest-dom majors used to be ignored here + # too, both blocked on Node >=22 while CI and Docker ran Node 20. That + # wall is gone — Node 20 reached EOL on 2026-04-30 and the toolchain moved + # to Node 22 — so both were taken and the ignores removed rather than left + # with a rationale that no longer holds. - dependency-name: "@vitejs/plugin-react" update-types: ["version-update:semver-major"] - - dependency-name: "@testing-library/jest-dom" - update-types: ["version-update:semver-major"] - - dependency-name: "jsdom" - update-types: ["version-update:semver-major"] # GitHub Actions workflow pins. - package-ecosystem: "github-actions" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index aa3c49e1..d5bb32d7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -54,7 +54,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "20" + node-version: "22" cache: npm cache-dependency-path: frontend/package-lock.json diff --git a/.github/workflows/wiki.yml b/.github/workflows/wiki.yml index 0320cc0e..2aaff61e 100644 --- a/.github/workflows/wiki.yml +++ b/.github/workflows/wiki.yml @@ -22,7 +22,7 @@ jobs: - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 with: - node-version: "20" + node-version: "22" - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0 with: diff --git a/Dockerfile b/Dockerfile index 270766d8..0ce93e2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,8 +1,8 @@ # ============================================================================ # Stage 1: Build frontend # ============================================================================ -FROM node:20-slim@sha256:2cf067cfed83d5ea958367df9f966191a942351a2df77d6f0193e162b5febfc0 AS frontend-build -# node:20-slim digest resolved 2026-07-13 +FROM node:22-slim@sha256:6c74791e557ce11fc957704f6d4fe134a7bc8d6f5ca4403205b2966bd488f6b3 AS frontend-build +# node:22-slim digest resolved 2026-07-28 WORKDIR /app/frontend COPY frontend/package.json frontend/package-lock.json ./ diff --git a/docker-compose.yml b/docker-compose.yml index 2ace7c71..2cbd411b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -59,7 +59,7 @@ services: restart: unless-stopped frontend: - image: node:20@sha256:8f693eaa7e0a8e71560c9a82b55fd54c2ae920a2ba5d2cde28bac7d1c01c9ba5 # node:20 digest resolved 2026-07-13 + image: node:22@sha256:5647be709086c696ff32edaaf1c70cd26d1da6ab2b39c32f3c7b4c4a31957e37 # node:22 digest resolved 2026-07-28 working_dir: /app ports: - "127.0.0.1:5899:5899" diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c1dff986..28f10c61 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -21,7 +21,7 @@ "react-dom": "^19.2.8", "react-i18next": "^17.0.11", "react-markdown": "^9.0.0", - "react-router-dom": "^7.18.1", + "react-router": "^8.3.0", "rehype-highlight": "^7.0.0", "rehype-katex": "^7.0.1", "remark-gfm": "^4.0.1", @@ -32,7 +32,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.20", - "@testing-library/jest-dom": "^6.9.1", + "@testing-library/jest-dom": "^7.0.0", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/react": "^19.2.17", @@ -40,7 +40,7 @@ "@vitejs/plugin-react": "^4.3.0", "@vitest/coverage-v8": "^4.1.10", "autoprefixer": "^10.5.4", - "jsdom": "^29.1.1", + "jsdom": "^30.0.0", "postcss": "^8.5.23", "tailwindcss": "^3.4.0", "typescript": "^5.7.0", @@ -69,56 +69,58 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "5.1.11", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-5.1.11.tgz", - "integrity": "sha512-KVw6qIiCTUQhByfTd78h2yD1/00waTmm9uy/R7Ck/ctUyAPj+AEDLkQIdJW0T8+qGgj3j5bpNKK7Q3G+LedJWg==", + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-6.0.5.tgz", + "integrity": "sha512-mbhpPMmnw/kwW19aRNmSUl1QzLbdGo1SCuE49BT98MNwqF6zaHb3o2owssFc/PEO/4t2UjqtCNwocuDtJornzA==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/generational-cache": "^1.0.1", - "@csstools/css-calc": "^3.2.0", - "@csstools/css-color-parser": "^4.1.0", + "@csstools/css-calc": "^3.2.1", + "@csstools/css-color-parser": "^4.1.9", "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0" + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.5.2" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.13.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" } }, "node_modules/@asamuzakjp/dom-selector": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-7.1.1.tgz", - "integrity": "sha512-67RZDnYRc8H/8MLDgQCDE//zoqVFwajkepHZgmXrbwybzXOEwOWGPYGmALYl9J2DOLfFPPs6kKCqmbzV895hTQ==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-8.3.0.tgz", + "integrity": "sha512-UJLfKXBhrc8i1vH2eJXuYQMwlsLKWFw3O+CPqXSuVEiikeAim3UgrfWX0k4tA/X8cRFM8iZ7OaqBokFGbYusdg==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/generational-cache": "^1.0.1", - "@asamuzakjp/nwsapi": "^2.3.9", "bidi-js": "^1.0.3", "css-tree": "^3.2.1", - "is-potential-custom-element-name": "^1.0.1" + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.5.2" }, "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "^22.13.0 || >=24.0.0" } }, - "node_modules/@asamuzakjp/generational-cache": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@asamuzakjp/generational-cache/-/generational-cache-1.0.1.tgz", - "integrity": "sha512-wajfB8KqzMCN2KGNFdLkReeHncd0AslUSrvHVvvYWuU8ghncRJoA50kT3zP9MVL0+9g4/67H+cdvBskj9THPzg==", + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", "dev": true, - "license": "MIT", + "license": "BlueOak-1.0.0", "engines": { - "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + "node": "20 || >=22" } }, - "node_modules/@asamuzakjp/nwsapi": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@asamuzakjp/nwsapi/-/nwsapi-2.3.9.tgz", - "integrity": "sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==", - "dev": true, - "license": "MIT" - }, "node_modules/@babel/code-frame": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", @@ -454,9 +456,9 @@ } }, "node_modules/@csstools/css-calc": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.2.1.tgz", - "integrity": "sha512-DtdHlgXh5ZkA43cwBcAm+huzgJiwx3ZTWVjBs94kwz2xKqSimDA3lBgCjphYgwgVUMWatSM0pDd8TILB1yrVVg==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", "dev": true, "funding": [ { @@ -478,9 +480,9 @@ } }, "node_modules/@csstools/css-color-parser": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.9.tgz", - "integrity": "sha512-paQcIaOO53Rk5+YrBaBjm/SgrV4INImjo2BT1DtQRYr+XeTRbeAYlS+jxXp9drqvKmtFnWRJKIalDLhZZDu42A==", + "version": "4.1.10", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.1.10.tgz", + "integrity": "sha512-UZhQLIUyJaaMepqehrCODwCg2KW25vFvLWBmqYFaPclYvvxzj/sG8LBOhBFCp11i9uE7t1EyS+RAoV9tztPFyw==", "dev": true, "funding": [ { @@ -495,7 +497,7 @@ "license": "MIT", "dependencies": { "@csstools/color-helpers": "^6.1.0", - "@csstools/css-calc": "^3.2.1" + "@csstools/css-calc": "^3.3.0" }, "engines": { "node": ">=20.19.0" @@ -1538,9 +1540,9 @@ } }, "node_modules/@testing-library/jest-dom": { - "version": "6.9.1", - "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.9.1.tgz", - "integrity": "sha512-zIcONa+hVtVSSep9UT3jZ5rizo2BsxgyDYU7WFD5eICBE7no3881HGeb/QkGfsJs6JTkY1aQhT7rIPC7e+0nnA==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-7.0.0.tgz", + "integrity": "sha512-HKAH9C6mBo5yBG6yRO5i43L2iisencAo5z+o5P/saHUoY+miC5ivXRxHBJcFyB5ypPNxHJdK3BoF/3O4DIptMg==", "dev": true, "license": "MIT", "dependencies": { @@ -1552,9 +1554,12 @@ "redent": "^3.0.0" }, "engines": { - "node": ">=14", + "node": ">=22", "npm": ">=6", "yarn": ">=1" + }, + "peerDependencies": { + "@testing-library/dom": ">=10 <11" } }, "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": { @@ -2314,18 +2319,11 @@ "dev": true, "license": "MIT" }, - "node_modules/cookie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", - "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" - } + "node_modules/cookie-es": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-3.1.1.tgz", + "integrity": "sha512-UaXxwISYJPTr9hwQxMFYZ7kNhSXboMXP+Z3TRX6f1/NyaGPfuNUZOWP1pUEb75B2HjfklIYLVRfWiFZJyC6Npg==", + "license": "MIT" }, "node_modules/css-tree": { "version": "3.2.1", @@ -3212,39 +3210,39 @@ "license": "MIT" }, "node_modules/jsdom": { - "version": "29.1.1", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-29.1.1.tgz", - "integrity": "sha512-ECi4Fi2f7BdJtUKTflYRTiaMxIB0O6zfR1fX0GXpUrf6flp8QIYn1UT20YQqdSOfk2dfkCwS8LAFoJDEppNK5Q==", + "version": "30.0.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.0.0.tgz", + "integrity": "sha512-JQHfRGmmKmaZoUAvIgff5jjG/0SzTQlGz8c7t72KzBzo8ZULEjAjnYE0sNwBOUA4QtWwYE2xoYitg8NFsmiYxA==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^5.1.11", - "@asamuzakjp/dom-selector": "^7.1.1", + "@asamuzakjp/css-color": "^6.0.5", + "@asamuzakjp/dom-selector": "^8.2.5", "@bramus/specificity": "^2.4.2", - "@csstools/css-syntax-patches-for-csstree": "^1.1.3", - "@exodus/bytes": "^1.15.0", + "@csstools/css-syntax-patches-for-csstree": "^1.1.6", + "@exodus/bytes": "^1.15.1", "css-tree": "^3.2.1", "data-urls": "^7.0.0", "decimal.js": "^10.6.0", "html-encoding-sniffer": "^6.0.0", "is-potential-custom-element-name": "^1.0.1", - "lru-cache": "^11.3.5", + "lru-cache": "^11.5.2", "parse5": "^8.0.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^6.0.1", - "undici": "^7.25.0", + "tough-cookie": "^6.0.2", + "undici": "^8.7.0", "w3c-xmlserializer": "^5.0.0", "webidl-conversions": "^8.0.1", "whatwg-mimetype": "^5.0.0", - "whatwg-url": "^16.0.1", + "whatwg-url": "^17.1.0", "xml-name-validator": "^5.0.0" }, "engines": { - "node": "^20.19.0 || ^22.13.0 || >=24.0.0" + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "canvas": "^3.0.0" + "canvas": "^3.2.3" }, "peerDependenciesMeta": { "canvas": { @@ -3262,6 +3260,21 @@ "node": "20 || >=22" } }, + "node_modules/jsdom/node_modules/whatwg-url": { + "version": "17.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.1.0.tgz", + "integrity": "sha512-3GeworPmc2ZfEEHP7lEbUfBX/L75wdEsi0rLNhXcXxnoN5jyq0SL5gCy06SGW2cyTIZdTvWIDQNQoza++vKeaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.15.1", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^22.14.0 || >=24.0.0" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -4897,20 +4910,19 @@ } }, "node_modules/react-router": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.1.tgz", - "integrity": "sha512-GDLgg3i3uM0aeJO3Fm+TCS+sDQ7gu12T6x0qdTEzcwqEfleci7JwugVNIF3U//0FWKnJT7ptG+20B2jfDqnZAg==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-8.3.0.tgz", + "integrity": "sha512-qyPMvW83jGIct3yiieisxdk9M745anqhpIMKN5m1t6yBMfgVPpt77aHOqs5fUlEJRMCGffg9BaQLH9oPVOL7xQ==", "license": "MIT", "dependencies": { - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0" + "cookie-es": "^3.1.1" }, "engines": { - "node": ">=20.0.0" + "node": ">=22.22.0" }, "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" + "react": ">=19.2.7", + "react-dom": ">=19.2.7" }, "peerDependenciesMeta": { "react-dom": { @@ -4918,22 +4930,6 @@ } } }, - "node_modules/react-router-dom": { - "version": "7.18.1", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.1.tgz", - "integrity": "sha512-KaZh+X/6UtEp28x51AUYZDMg9NGoz2ja3dNHa+ta/tk40vCzKhQ/RypCWBMLbmDr6//E24Vv5uPsrqXFozdkAg==", - "license": "MIT", - "dependencies": { - "react-router": "7.18.1" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -5254,12 +5250,6 @@ "semver": "bin/semver.js" } }, - "node_modules/set-cookie-parser": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", - "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", - "license": "MIT" - }, "node_modules/siginfo": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", @@ -5573,22 +5563,22 @@ } }, "node_modules/tldts": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.2.tgz", - "integrity": "sha512-kCwffuaH8ntKtygnWe1b4BJKWiCUH30n5KfoTr6IchcXOwR7chAOFJxFrH3vjANafUYrIA4a7SDL+nn7SiR4Sw==", + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.9.tgz", + "integrity": "sha512-3kZ8wQQ/k5DrChD4X4FVvr2D7E5uoRgAqkPyLpSCGUvqOvqu+JEdr3mwMUaVWb+vMHZaKhF5fp2PBigKsui7hA==", "dev": true, "license": "MIT", "dependencies": { - "tldts-core": "^7.4.2" + "tldts-core": "^7.4.9" }, "bin": { "tldts": "bin/cli.js" } }, "node_modules/tldts-core": { - "version": "7.4.2", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.2.tgz", - "integrity": "sha512-nwEyF4vl4RSJjwSjBUmOSxc3BFPoIFdlRthJ6e+5v9P3bHNsoD06UjuqMUspqp7vsEZ1beaHi1km+optiE17yA==", + "version": "7.4.9", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.9.tgz", + "integrity": "sha512-DxKfPBI52p2msTEu7MPhdpdDTBhhVQg1a/8PjQckeyAvO13eMYElX545grIp6nnTGIMZlRvFZPvFhvI/WIz2Vg==", "dev": true, "license": "MIT" }, @@ -5606,9 +5596,9 @@ } }, "node_modules/tough-cookie": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.1.tgz", - "integrity": "sha512-LktZQb3IeoUWB9lqR5EWTHgW/VTITCXg4D21M+lvybRVdylLrRMnqaIONLVb5mav8vM19m44HIcGq4qASeu2Qw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -5679,13 +5669,13 @@ } }, "node_modules/undici": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.28.0.tgz", - "integrity": "sha512-cRZYrTDwWznlnRiPjggAGxZXanty6M8RV1ff8Wm4LWXBp7/IG8v5DnOm74DtUBp9OONpK75YlPnIjQqX0dBDtA==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", + "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", "dev": true, "license": "MIT", "engines": { - "node": ">=20.18.1" + "node": ">=22.19.0" } }, "node_modules/unified": { diff --git a/frontend/package.json b/frontend/package.json index a51d7ef7..c439531b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -25,7 +25,7 @@ "react-dom": "^19.2.8", "react-i18next": "^17.0.11", "react-markdown": "^9.0.0", - "react-router-dom": "^7.18.1", + "react-router": "^8.3.0", "rehype-highlight": "^7.0.0", "rehype-katex": "^7.0.1", "remark-gfm": "^4.0.1", @@ -36,7 +36,7 @@ }, "devDependencies": { "@tailwindcss/typography": "^0.5.20", - "@testing-library/jest-dom": "^6.9.1", + "@testing-library/jest-dom": "^7.0.0", "@testing-library/react": "^16.3.2", "@testing-library/user-event": "^14.6.1", "@types/react": "^19.2.17", @@ -44,7 +44,7 @@ "@vitejs/plugin-react": "^4.3.0", "@vitest/coverage-v8": "^4.1.10", "autoprefixer": "^10.5.4", - "jsdom": "^29.1.1", + "jsdom": "^30.0.0", "postcss": "^8.5.23", "tailwindcss": "^3.4.0", "typescript": "^5.7.0", diff --git a/frontend/src/components/chat/RunCompleteCard.tsx b/frontend/src/components/chat/RunCompleteCard.tsx index b9950878..b07abbdb 100644 --- a/frontend/src/components/chat/RunCompleteCard.tsx +++ b/frontend/src/components/chat/RunCompleteCard.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { memo, useEffect, useState, useCallback } from "react"; -import { Link } from "react-router-dom"; +import { Link } from "react-router"; import { BarChart3, Code2, FileText, Loader2 } from "lucide-react"; import { api } from "@/lib/api"; import { AgentAvatar } from "./AgentAvatar"; diff --git a/frontend/src/components/layout/Layout.tsx b/frontend/src/components/layout/Layout.tsx index e760c314..089f5db7 100644 --- a/frontend/src/components/layout/Layout.tsx +++ b/frontend/src/components/layout/Layout.tsx @@ -1,6 +1,6 @@ import { useTranslation } from "react-i18next"; import { useEffect, useRef, useState } from "react"; -import { Link, Outlet, useLocation, useSearchParams } from "react-router-dom"; +import { Link, Outlet, useLocation, useSearchParams } from "react-router"; import { Activity, BarChart3, Bot, Check, ChevronDown, FileText, Languages, Moon, Sun, Plus, Trash2, Pencil, MessageSquare, ChevronsLeft, ChevronsRight, Settings, Layers, Loader2 } from "lucide-react"; import { cn } from "@/lib/utils"; import { useDarkMode } from "@/hooks/useDarkMode"; diff --git a/frontend/src/main.tsx b/frontend/src/main.tsx index b7130ef8..7c0069a0 100644 --- a/frontend/src/main.tsx +++ b/frontend/src/main.tsx @@ -1,7 +1,7 @@ import './i18n'; import { StrictMode } from "react"; import { createRoot } from "react-dom/client"; -import { RouterProvider } from "react-router-dom"; +import { RouterProvider } from "react-router"; import { Toaster } from "sonner"; import { ErrorBoundary } from "./components/common/ErrorBoundary"; import { router } from "./router"; diff --git a/frontend/src/pages/Agent.tsx b/frontend/src/pages/Agent.tsx index 0bce0336..73bc764f 100644 --- a/frontend/src/pages/Agent.tsx +++ b/frontend/src/pages/Agent.tsx @@ -1,6 +1,6 @@ import { useTranslation } from 'react-i18next'; import { useEffect, useRef, useState, useMemo, useCallback, type FormEvent } from "react"; -import { useSearchParams } from "react-router-dom"; +import { useSearchParams } from "react-router"; import { Send, Loader2, ArrowDown, Square, Download, Plus, Paperclip, X, Users, Target, ChevronDown, Pencil, Check, Play, OctagonX, Activity, Ban, CheckCircle2, Landmark } from "lucide-react"; import { toast } from "sonner"; import { useAgentStore } from "@/stores/agent"; diff --git a/frontend/src/pages/AlphaZoo.tsx b/frontend/src/pages/AlphaZoo.tsx index b3e80f6a..8d8dbfd6 100644 --- a/frontend/src/pages/AlphaZoo.tsx +++ b/frontend/src/pages/AlphaZoo.tsx @@ -15,7 +15,7 @@ import i18n from '@/i18n'; */ import { useEffect, useMemo, useRef, useState, type FormEvent } from "react"; -import { Link, useLocation, useNavigate, useParams } from "react-router-dom"; +import { Link, useLocation, useNavigate, useParams } from "react-router"; import { Layers, Search, diff --git a/frontend/src/pages/Home.tsx b/frontend/src/pages/Home.tsx index 73d475c4..e3c0ab1c 100644 --- a/frontend/src/pages/Home.tsx +++ b/frontend/src/pages/Home.tsx @@ -1,4 +1,4 @@ -import { Link } from "react-router-dom"; +import { Link } from "react-router"; import { ArrowRight, Bot, BarChart3, Zap, UserCircle2, MessageSquarePlus, SearchCode, LineChart, ShieldCheck } from "lucide-react"; import { useTranslation } from "react-i18next"; diff --git a/frontend/src/pages/Reports.tsx b/frontend/src/pages/Reports.tsx index 91d6a6e4..dd16cbc8 100644 --- a/frontend/src/pages/Reports.tsx +++ b/frontend/src/pages/Reports.tsx @@ -1,6 +1,6 @@ import { useEffect, useMemo, useState } from "react"; import { useTranslation } from "react-i18next"; -import { Link } from "react-router-dom"; +import { Link } from "react-router"; import { AlertTriangle, ArrowRight, diff --git a/frontend/src/pages/RunDetail.tsx b/frontend/src/pages/RunDetail.tsx index 23502865..6af1e9f0 100644 --- a/frontend/src/pages/RunDetail.tsx +++ b/frontend/src/pages/RunDetail.tsx @@ -1,7 +1,7 @@ import i18n from '@/i18n'; import { useEffect, useRef, useState } from "react"; import type { ReactNode } from "react"; -import { useParams, useNavigate } from "react-router-dom"; +import { useParams, useNavigate } from "react-router"; import { AlertTriangle, ArrowLeft, diff --git a/frontend/src/pages/__tests__/Reports.test.tsx b/frontend/src/pages/__tests__/Reports.test.tsx index c15da504..0a05a8c5 100644 --- a/frontend/src/pages/__tests__/Reports.test.tsx +++ b/frontend/src/pages/__tests__/Reports.test.tsx @@ -1,5 +1,5 @@ import { fireEvent, render, screen } from "@testing-library/react"; -import { MemoryRouter } from "react-router-dom"; +import { MemoryRouter } from "react-router"; import { Reports } from "../Reports"; const apiMock = vi.hoisted(() => ({ diff --git a/frontend/src/pages/__tests__/RunDetail.test.tsx b/frontend/src/pages/__tests__/RunDetail.test.tsx index 9d223c56..2079a65d 100644 --- a/frontend/src/pages/__tests__/RunDetail.test.tsx +++ b/frontend/src/pages/__tests__/RunDetail.test.tsx @@ -1,5 +1,5 @@ import { act, fireEvent, render, screen, waitFor } from "@testing-library/react"; -import { createMemoryRouter, RouterProvider } from "react-router-dom"; +import { createMemoryRouter, RouterProvider } from "react-router"; import { RunDetail } from "../RunDetail"; import type { RunData } from "@/lib/api"; diff --git a/frontend/src/router.tsx b/frontend/src/router.tsx index a57fc735..014d355b 100644 --- a/frontend/src/router.tsx +++ b/frontend/src/router.tsx @@ -1,5 +1,5 @@ import { Suspense, lazy, type ComponentType } from "react"; -import { createBrowserRouter } from "react-router-dom"; +import { createBrowserRouter } from "react-router"; import { Layout } from "@/components/layout/Layout"; const Home = lazy(() => import("@/pages/Home").then((m) => ({ default: m.Home }))); diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index 9889361a..a3b45650 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -53,7 +53,7 @@ export default defineConfig(({ mode }) => { rollupOptions: { output: { manualChunks: { - "vendor-react": ["react", "react-dom", "react-router-dom"], + "vendor-react": ["react", "react-dom", "react-router"], "vendor-charts": ["echarts"], }, },