From d09dfb15354a52c33606e96ec73528e5c25a0e3e Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Wed, 8 Jul 2026 19:15:17 +0000 Subject: [PATCH 1/4] Optimize dev rebuild defaults --- .../package.json | 2 +- config/package.json | 4 +- examples/client-only/package.json | 2 +- examples/cloudflare/package.json | 2 +- examples/custom-node-server/package.json | 2 +- examples/default-template/package.json | 2 +- .../tests/e2e/dev-route-watch.test.ts | 4 - examples/epic-stack/package.json | 6 +- .../federation/epic-stack-remote/package.json | 8 +- examples/federation/epic-stack/package.json | 8 +- examples/prerender/package.json | 2 +- examples/spa-mode/package.json | 2 +- package.json | 10 +- pnpm-lock.yaml | 1125 +++++++---------- rslib.config.ts | 4 +- scripts/benchmark/results.mts | 2 +- src/build-output-transforms.ts | 36 +- src/dev-background-resources.ts | 2 - src/index.ts | 84 +- src/parallel-route-transform-protocol.ts | 35 - src/parallel-route-transform-worker.ts | 82 -- src/parallel-route-transforms.ts | 445 +------ src/route-module-transform-loader.ts | 46 + src/types.ts | 9 +- tests/build-output-transforms.test.ts | 52 +- tests/dev-runtime.integration.test.ts | 41 +- tests/features.test.ts | 2 +- tests/index.test.ts | 30 +- tests/parallel-route-transforms.test.ts | 565 +-------- tests/route-module-transform-loader.test.ts | 64 + 30 files changed, 815 insertions(+), 1863 deletions(-) delete mode 100644 src/parallel-route-transform-protocol.ts delete mode 100644 src/parallel-route-transform-worker.ts create mode 100644 src/route-module-transform-loader.ts create mode 100644 tests/route-module-transform-loader.test.ts diff --git a/benchmarks/synthetic-web-bundler-benchmark/package.json b/benchmarks/synthetic-web-bundler-benchmark/package.json index 3e87bcae..55c29d06 100644 --- a/benchmarks/synthetic-web-bundler-benchmark/package.json +++ b/benchmarks/synthetic-web-bundler-benchmark/package.json @@ -37,7 +37,7 @@ "devDependencies": { "@babel/core": "7.29.0", "@react-router/dev": "7.14.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-babel": "2.0.0", "@rsbuild/plugin-react": "2.1.0", "@rsbuild/plugin-svgr": "2.0.4", diff --git a/config/package.json b/config/package.json index 8a53e8c1..2ca96bfa 100644 --- a/config/package.json +++ b/config/package.json @@ -3,8 +3,8 @@ "version": "1.0.1", "private": true, "devDependencies": { - "@rsbuild/core": "2.1.0", - "@rslib/core": "0.22.1", + "@rsbuild/core": "2.1.5", + "@rslib/core": "0.23.2", "@types/node": "^25.0.10", "typescript": "^5.9.3" } diff --git a/examples/client-only/package.json b/examples/client-only/package.json index 948fa29d..9c582209 100644 --- a/examples/client-only/package.json +++ b/examples/client-only/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@playwright/test": "^1.58.0", "@react-router/dev": "^7.13.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "^2.1.0", "@types/node": "^25.0.10", "@types/react": "^19.2.10", diff --git a/examples/cloudflare/package.json b/examples/cloudflare/package.json index 6877fa51..7edb30da 100644 --- a/examples/cloudflare/package.json +++ b/examples/cloudflare/package.json @@ -23,7 +23,7 @@ "@playwright/test": "^1.58.0", "@react-router/cloudflare": "^7.13.0", "@react-router/dev": "^7.13.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "^2.1.0", "@tailwindcss/postcss": "^4.1.18", "@types/node": "^25.0.10", diff --git a/examples/custom-node-server/package.json b/examples/custom-node-server/package.json index 76ba9205..cd0610da 100644 --- a/examples/custom-node-server/package.json +++ b/examples/custom-node-server/package.json @@ -30,7 +30,7 @@ "devDependencies": { "@playwright/test": "^1.58.0", "@react-router/dev": "^7.13.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "^2.1.0", "@rsdoctor/rspack-plugin": "^1.5.13", "@tailwindcss/postcss": "^4.1.18", diff --git a/examples/default-template/package.json b/examples/default-template/package.json index f66c8572..8deac493 100644 --- a/examples/default-template/package.json +++ b/examples/default-template/package.json @@ -23,7 +23,7 @@ "devDependencies": { "@playwright/test": "^1.58.0", "@react-router/dev": "^7.13.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-less": "^1.6.4", "@rsbuild/plugin-react": "^2.1.0", "@rsbuild/plugin-sass": "^1.5.3", diff --git a/examples/default-template/tests/e2e/dev-route-watch.test.ts b/examples/default-template/tests/e2e/dev-route-watch.test.ts index 56dceef2..cc0e3ed2 100644 --- a/examples/default-template/tests/e2e/dev-route-watch.test.ts +++ b/examples/default-template/tests/e2e/dev-route-watch.test.ts @@ -144,7 +144,6 @@ test.describe('dev route watch', () => { }) => { await page.goto('/'); await expect(page.locator('h1')).toContainText('Welcome to React Router'); - const restartMarkerBeforeAdd = readRestartMarkerVersion(); writeFileSync( addedRoutePath, @@ -161,9 +160,6 @@ test.describe('dev route watch', () => { await page.goto(addedRouteUrl); await expect(page.locator('h1')).toHaveText(addedRouteText); - await expect - .poll(readRestartMarkerVersion, { timeout: 10000 }) - .not.toBe(restartMarkerBeforeAdd); const restartMarkerBefore = readRestartMarkerVersion(); writeFileSync( addedRoutePath, diff --git a/examples/epic-stack/package.json b/examples/epic-stack/package.json index 91a86db8..000136b5 100644 --- a/examples/epic-stack/package.json +++ b/examples/epic-stack/package.json @@ -66,7 +66,7 @@ "@react-router/node": "^7.13.0", "@react-router/remix-routes-option-adapter": "7.13.0", "@remix-run/server-runtime": "2.17.4", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "2.1.0", "@sentry/node": "10.37.0", "@sentry/profiling-node": "10.37.0", @@ -121,6 +121,8 @@ "@faker-js/faker": "10.2.0", "@playwright/test": "1.58.0", "@react-router/dev": "^7.13.0", + "@rstest/core": "0.11.0", + "@rstest/coverage-istanbul": "0.11.0", "@sentry/vite-plugin": "4.8.0", "@sly-cli/sly": "2.1.1", "@tailwindcss/nesting": "0.0.0-insiders.565cd3e", @@ -144,8 +146,6 @@ "@types/react-dom": "19.2.3", "@types/set-cookie-parser": "2.4.10", "@types/source-map-support": "0.5.10", - "@rstest/core": "0.8.1", - "@rstest/coverage-istanbul": "0.2.0", "@vitejs/plugin-react": "5.1.2", "autoprefixer": "10.4.23", "enforce-unique": "1.3.0", diff --git a/examples/federation/epic-stack-remote/package.json b/examples/federation/epic-stack-remote/package.json index c4bb8d62..4e3a731c 100644 --- a/examples/federation/epic-stack-remote/package.json +++ b/examples/federation/epic-stack-remote/package.json @@ -48,8 +48,8 @@ "@epic-web/invariant": "1.0.0", "@epic-web/remember": "1.1.0", "@epic-web/totp": "4.0.1", - "@mjackson/headers": "0.6.1", "@mjackson/form-data-parser": "0.9.1", + "@mjackson/headers": "0.6.1", "@module-federation/enhanced": "2.5.1", "@module-federation/node": "2.7.44", "@module-federation/rsbuild-plugin": "2.5.1", @@ -70,7 +70,7 @@ "@react-router/node": "^7.13.0", "@react-router/remix-routes-option-adapter": "7.13.0", "@remix-run/server-runtime": "2.17.4", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "2.1.0", "@sentry/node": "10.37.0", "@sentry/profiling-node": "10.37.0", @@ -124,6 +124,8 @@ "@faker-js/faker": "10.2.0", "@playwright/test": "1.58.0", "@react-router/dev": "^7.13.0", + "@rstest/core": "0.11.0", + "@rstest/coverage-istanbul": "0.11.0", "@sly-cli/sly": "2.1.1", "@tailwindcss/nesting": "0.0.0-insiders.565cd3e", "@tailwindcss/postcss": "^4.1.18", @@ -146,8 +148,6 @@ "@types/react-dom": "19.2.3", "@types/set-cookie-parser": "2.4.10", "@types/source-map-support": "0.5.10", - "@rstest/core": "0.8.1", - "@rstest/coverage-istanbul": "0.2.0", "autoprefixer": "10.4.23", "enforce-unique": "1.3.0", "esbuild": "0.27.2", diff --git a/examples/federation/epic-stack/package.json b/examples/federation/epic-stack/package.json index 817c90b4..1ead6162 100644 --- a/examples/federation/epic-stack/package.json +++ b/examples/federation/epic-stack/package.json @@ -48,8 +48,8 @@ "@epic-web/invariant": "1.0.0", "@epic-web/remember": "1.1.0", "@epic-web/totp": "4.0.1", - "@mjackson/headers": "0.6.1", "@mjackson/form-data-parser": "0.9.1", + "@mjackson/headers": "0.6.1", "@module-federation/enhanced": "2.5.1", "@module-federation/node": "2.7.44", "@module-federation/rsbuild-plugin": "2.5.1", @@ -70,7 +70,7 @@ "@react-router/node": "^7.13.0", "@react-router/remix-routes-option-adapter": "7.13.0", "@remix-run/server-runtime": "2.17.4", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "2.1.0", "@sentry/node": "10.37.0", "@sentry/profiling-node": "10.37.0", @@ -124,6 +124,8 @@ "@faker-js/faker": "10.2.0", "@playwright/test": "1.58.0", "@react-router/dev": "^7.13.0", + "@rstest/core": "0.11.0", + "@rstest/coverage-istanbul": "0.11.0", "@sly-cli/sly": "2.1.1", "@tailwindcss/nesting": "0.0.0-insiders.565cd3e", "@tailwindcss/postcss": "^4.1.18", @@ -146,8 +148,6 @@ "@types/react-dom": "19.2.3", "@types/set-cookie-parser": "2.4.10", "@types/source-map-support": "0.5.10", - "@rstest/core": "0.8.1", - "@rstest/coverage-istanbul": "0.2.0", "autoprefixer": "10.4.23", "enforce-unique": "1.3.0", "esbuild": "0.27.2", diff --git a/examples/prerender/package.json b/examples/prerender/package.json index 4f5a09ab..73c378bb 100644 --- a/examples/prerender/package.json +++ b/examples/prerender/package.json @@ -21,7 +21,7 @@ "devDependencies": { "@playwright/test": "^1.58.0", "@react-router/dev": "^7.13.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "^2.1.0", "@tailwindcss/postcss": "^4.1.18", "@types/node": "^25.0.10", diff --git a/examples/spa-mode/package.json b/examples/spa-mode/package.json index fd108c8e..43eb07af 100644 --- a/examples/spa-mode/package.json +++ b/examples/spa-mode/package.json @@ -21,7 +21,7 @@ "devDependencies": { "@playwright/test": "^1.58.0", "@react-router/dev": "^7.13.0", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "^2.1.0", "@tailwindcss/postcss": "^4.1.18", "@types/node": "^25.0.10", diff --git a/package.json b/package.json index fcda9e90..e0a41624 100644 --- a/package.json +++ b/package.json @@ -92,12 +92,12 @@ "@changesets/cli": "^2.29.8", "@react-router/dev": "^8.0.1", "@rsbuild/config": "workspace:*", - "@rsbuild/core": "2.1.0", + "@rsbuild/core": "2.1.5", "@rsbuild/plugin-react": "2.1.0", - "@rslib/core": "^0.22.1", - "@rspack/core": "2.1.0", - "@rstest/core": "^0.8.1", - "@rstest/coverage-istanbul": "^0.2.0", + "@rslib/core": "^0.23.2", + "@rspack/core": "2.1.3", + "@rstest/core": "^0.11.0", + "@rstest/coverage-istanbul": "^0.11.0", "@swc/helpers": "^0.5.23", "@types/fs-extra": "11.0.4", "@types/jsesc": "^3.0.3", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 01b2da70..a0a7a174 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -19,7 +19,7 @@ importers: version: 0.13.3 '@rspack/plugin-react-refresh': specifier: ^2.0.2 - version: 2.0.2(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(react-refresh@0.18.0) + version: 2.0.2(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(react-refresh@0.18.0) execa: specifier: ^9.6.1 version: 9.6.1 @@ -56,28 +56,28 @@ importers: version: 2.31.0(@types/node@25.0.10) '@react-router/dev': specifier: ^8.0.1 - version: 8.0.1(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 8.0.1(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/config': specifier: workspace:* version: link:config '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@rslib/core': - specifier: ^0.22.1 - version: 0.22.1(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)(typescript@5.9.3) + specifier: ^0.23.2 + version: 0.23.2(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)(typescript@5.9.3) '@rspack/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + specifier: 2.1.3 + version: 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) '@rstest/core': - specifier: ^0.8.1 - version: 0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0)) + specifier: ^0.11.0 + version: 0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0)) '@rstest/coverage-istanbul': - specifier: ^0.2.0 - version: 0.2.0(@rstest/core@0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0))) + specifier: ^0.11.0 + version: 0.11.0(@rstest/core@0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0))) '@swc/helpers': specifier: ^0.5.23 version: 0.5.23 @@ -189,22 +189,22 @@ importers: version: 7.29.0 '@react-router/dev': specifier: 7.14.0 - version: 7.14.0(@react-router/serve@7.14.0(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@6.0.1-rc))(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@6.0.1-rc)(vite@7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.14.0(@react-router/serve@7.14.0(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@6.0.1-rc))(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@6.0.1-rc)(vite@7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-babel': specifier: 2.0.0 - version: 2.0.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)) + version: 2.0.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)) '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@rsbuild/plugin-svgr': specifier: 2.0.4 - version: 2.0.4(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(typescript@6.0.1-rc) + version: 2.0.4(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(typescript@6.0.1-rc) '@rsbuild/plugin-tailwindcss': specifier: 2.0.3 - version: 2.0.3(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + version: 2.0.3(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) '@types/babel__core': specifier: 7.20.5 version: 7.20.5 @@ -233,11 +233,11 @@ importers: config: devDependencies: '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rslib/core': - specifier: 0.22.1 - version: 0.22.1(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)(typescript@5.9.3) + specifier: 0.23.2 + version: 0.23.2(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)(typescript@5.9.3) '@types/node': specifier: ^25.0.10 version: 25.0.10 @@ -274,13 +274,13 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: ^2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@types/node': specifier: ^25.0.10 version: 25.0.10 @@ -298,7 +298,7 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) examples/cloudflare: dependencies: @@ -332,13 +332,13 @@ importers: version: 7.18.0(@cloudflare/workers-types@4.20260628.1)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: ^2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@tailwindcss/postcss': specifier: ^4.1.18 version: 4.3.1 @@ -393,16 +393,16 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: ^2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@rsdoctor/rspack-plugin': specifier: ^1.5.13 - version: 1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + version: 1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) '@tailwindcss/postcss': specifier: ^4.1.18 version: 4.3.1 @@ -457,19 +457,19 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-less': specifier: ^1.6.4 - version: 1.6.4(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + version: 1.6.4(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) '@rsbuild/plugin-react': specifier: ^2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@rsbuild/plugin-sass': specifier: ^1.5.3 - version: 1.5.3(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)) + version: 1.5.3(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)) '@tailwindcss/postcss': specifier: ^4.1.18 version: 4.3.1 @@ -487,7 +487,7 @@ importers: version: 10.1.0 react-router-devtools: specifier: ^6.2.0 - version: 6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) rsbuild-plugin-react-router: specifier: workspace:* version: link:../.. @@ -505,10 +505,10 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) vite-tsconfig-paths: specifier: ^6.0.5 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) examples/epic-stack: dependencies: @@ -583,16 +583,16 @@ importers: version: 7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) '@react-router/remix-routes-option-adapter': specifier: 7.13.0 - version: 7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3) + version: 7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3) '@remix-run/server-runtime': specifier: 2.17.4 version: 2.17.4(typescript@5.9.3) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@sentry/node': specifier: 10.37.0 version: 10.37.0 @@ -730,7 +730,7 @@ importers: version: 4.0.2(tailwindcss@4.1.18) vite-env-only: specifier: 3.0.3 - version: 3.0.3(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 3.0.3(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) zod: specifier: 3.25.76 version: 3.25.76 @@ -746,13 +746,13 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rstest/core': - specifier: 0.8.1 - version: 0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0)) + specifier: 0.11.0 + version: 0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0)) '@rstest/coverage-istanbul': - specifier: 0.2.0 - version: 0.2.0(@rstest/core@0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0))) + specifier: 0.11.0 + version: 0.11.0(@rstest/core@0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0))) '@sentry/vite-plugin': specifier: 4.8.0 version: 4.8.0(encoding@0.1.13) @@ -824,7 +824,7 @@ importers: version: 0.5.10 '@vitejs/plugin-react': specifier: 5.1.2 - version: 5.1.2(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 5.1.2(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) autoprefixer: specifier: 10.4.23 version: 10.4.23(postcss@8.5.16) @@ -872,7 +872,7 @@ importers: version: 5.9.3 vite: specifier: 7.3.1 - version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) examples/federation: devDependencies: @@ -911,13 +911,13 @@ importers: version: 0.6.1 '@module-federation/enhanced': specifier: 2.5.1 - version: 2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + version: 2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@module-federation/node': specifier: 2.7.44 - version: 2.7.44(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + version: 2.7.44(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@module-federation/rsbuild-plugin': specifier: 2.5.1 - version: 2.5.1(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + version: 2.5.1(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@nasa-gcn/remix-seo': specifier: 2.0.1 version: 2.0.1(@remix-run/react@2.17.5(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@remix-run/server-runtime@2.17.4(typescript@5.9.3)) @@ -965,16 +965,16 @@ importers: version: 7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) '@react-router/remix-routes-option-adapter': specifier: 7.13.0 - version: 7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3) + version: 7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3) '@remix-run/server-runtime': specifier: 2.17.4 version: 2.17.4(typescript@5.9.3) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@sentry/node': specifier: 10.37.0 version: 10.37.0 @@ -1125,13 +1125,13 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rstest/core': - specifier: 0.8.1 - version: 0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0)) + specifier: 0.11.0 + version: 0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0)) '@rstest/coverage-istanbul': - specifier: 0.2.0 - version: 0.2.0(@rstest/core@0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0))) + specifier: 0.11.0 + version: 0.11.0(@rstest/core@0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0))) '@sly-cli/sly': specifier: 2.1.1 version: 2.1.1(typescript@5.9.3) @@ -1275,13 +1275,13 @@ importers: version: 0.6.1 '@module-federation/enhanced': specifier: 2.5.1 - version: 2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + version: 2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@module-federation/node': specifier: 2.7.44 - version: 2.7.44(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + version: 2.7.44(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@module-federation/rsbuild-plugin': specifier: 2.5.1 - version: 2.5.1(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + version: 2.5.1(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@nasa-gcn/remix-seo': specifier: 2.0.1 version: 2.0.1(@remix-run/react@2.17.5(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(typescript@5.9.3))(@remix-run/server-runtime@2.17.4(typescript@5.9.3)) @@ -1329,16 +1329,16 @@ importers: version: 7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) '@react-router/remix-routes-option-adapter': specifier: 7.13.0 - version: 7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3) + version: 7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3) '@remix-run/server-runtime': specifier: 2.17.4 version: 2.17.4(typescript@5.9.3) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: 2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@sentry/node': specifier: 10.37.0 version: 10.37.0 @@ -1489,13 +1489,13 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rstest/core': - specifier: 0.8.1 - version: 0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0)) + specifier: 0.11.0 + version: 0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0)) '@rstest/coverage-istanbul': - specifier: 0.2.0 - version: 0.2.0(@rstest/core@0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0))) + specifier: 0.11.0 + version: 0.11.0(@rstest/core@0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0))) '@sly-cli/sly': specifier: 2.1.1 version: 2.1.1(typescript@5.9.3) @@ -1637,13 +1637,13 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: ^2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@tailwindcss/postcss': specifier: ^4.1.18 version: 4.3.1 @@ -1661,7 +1661,7 @@ importers: version: 10.1.0 react-router-devtools: specifier: ^6.2.0 - version: 6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) rsbuild-plugin-react-router: specifier: workspace:* version: link:../.. @@ -1682,10 +1682,10 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) vite-tsconfig-paths: specifier: ^6.0.5 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) examples/spa-mode: dependencies: @@ -1716,13 +1716,13 @@ importers: version: 1.58.0 '@react-router/dev': specifier: ^7.13.0 - version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + version: 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) '@rsbuild/core': - specifier: 2.1.0 - version: 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + specifier: 2.1.5 + version: 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@rsbuild/plugin-react': specifier: ^2.1.0 - version: 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + version: 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@tailwindcss/postcss': specifier: ^4.1.18 version: 4.3.1 @@ -1740,7 +1740,7 @@ importers: version: 10.1.0 react-router-devtools: specifier: ^6.2.0 - version: 6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) rsbuild-plugin-react-router: specifier: workspace:* version: link:../.. @@ -1761,10 +1761,10 @@ importers: version: 5.9.3 vite: specifier: ^7.3.1 - version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + version: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) vite-tsconfig-paths: specifier: ^6.0.5 - version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + version: 6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) packages: @@ -2203,6 +2203,9 @@ packages: '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/wasi-threads@1.2.1': resolution: {integrity: sha512-uTII7OYF+/Mes/MrcIOYp5yOtSMLBWSIoLPpcgwipoiKbli6k322tcoFsxoIIxPDqW01SQGAgko4EzZi2BNv2w==} @@ -2924,9 +2927,6 @@ packages: webpack: optional: true - '@module-federation/error-codes@0.22.0': - resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} - '@module-federation/error-codes@2.5.1': resolution: {integrity: sha512-3KIR8XbEW0Y+Fn8IAnxzDWMvXQWiS40Z1TE/Fft9aTeXP9dDAM7AiVhjTh5yF2csAwHSt/1LJVZbiCmS13mE8A==} @@ -2970,27 +2970,15 @@ packages: vue-tsc: optional: true - '@module-federation/runtime-core@0.22.0': - resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} - '@module-federation/runtime-core@2.5.1': resolution: {integrity: sha512-UMuMsWHXeMrm8Isl8YD6/s1jmTVau3SQhp9RO4Ln+eD2lrjM4hQSwOX2xPtfT1C1I4/E6hgyZQV1K1Q/3Zpr0Q==} - '@module-federation/runtime-tools@0.22.0': - resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} - '@module-federation/runtime-tools@2.5.1': resolution: {integrity: sha512-pYUNvaQQBEwP66TLrjmmfkDIrTmPnX0kK86HgClkWLQKkX/oCgnqDxEgNbjeCc75dwUvZP6fW2d0pZ5++XILTw==} - '@module-federation/runtime@0.22.0': - resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} - '@module-federation/runtime@2.5.1': resolution: {integrity: sha512-Tf33FIpnQMn8FjIUAQMtSTYQgGibfh5vEvJihFO3q/hG9LiWwLMErZvOz/+wcPsE81gzHjYPxQgMKGSP3BuG8g==} - '@module-federation/sdk@0.22.0': - resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} - '@module-federation/sdk@2.5.1': resolution: {integrity: sha512-FDhCx81ZCxX1oT/fyt/bW+gpPt287GR156E/Thv1yhb9XyNHGNkqe8zqJOipOMfb07E22OMzSzOulCBvAOgn3g==} peerDependencies: @@ -3002,9 +2990,6 @@ packages: '@module-federation/third-party-dts-extractor@2.5.1': resolution: {integrity: sha512-/jD/o2IivDgg6jGUgdb9NZtlJWeoz1uKcblGL2BxYVzzlKT+1YS7Y2idTl1tqp4hNdFnDlPpQv6WLdKiLoOPNw==} - '@module-federation/webpack-bundler-runtime@0.22.0': - resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} - '@module-federation/webpack-bundler-runtime@2.5.1': resolution: {integrity: sha512-0pUsP9aaWIUcfWUXqax/iSwozngORwf4RK0R1qTOYYC13qx+p4p1Ck28Rz6Tzj/6zpzJgcMQXR7nW4sL+ztaww==} @@ -3012,21 +2997,6 @@ packages: resolution: {integrity: sha512-EFd6cVbHsgLa6wa4RljGj6Wk75qoHxUSyc5asLyyPSyuhIcdS2Q3Phw6ImS1q+CkALthJRShiYfKANcQMuMqsQ==} engines: {node: '>=18'} - '@napi-rs/wasm-runtime@1.0.7': - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} - - '@napi-rs/wasm-runtime@1.1.4': - resolution: {integrity: sha512-3NQNNgA1YSlJb/kMH1ildASP9HW7/7kYnRI2szWJaofaS1hWmbGI4H+d3+22aGzXXN9IJ+n+GiFVcGipJP18ow==} - peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 - - '@napi-rs/wasm-runtime@1.1.5': - resolution: {integrity: sha512-AWPoBRJ9tsnVhor4sjO7rkni+7p+2IAEFj6cx06UgP10jkQHqay/36uRV/bFkgrh18D9vb4cr8Q0Pthskgzy+Q==} - peerDependencies: - '@emnapi/core': ^1.7.1 - '@emnapi/runtime': ^1.7.1 - '@napi-rs/wasm-runtime@1.1.6': resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} peerDependencies: @@ -4473,23 +4443,8 @@ packages: cpu: [x64] os: [win32] - '@rsbuild/core@1.7.2': - resolution: {integrity: sha512-VAFO6cM+cyg2ntxNW6g3tB2Jc5J5mpLjLluvm7VtW2uceNzyUlVv41o66Yp1t1ikxd3ljtqegViXem62JqzveA==} - engines: {node: '>=18.12.0'} - hasBin: true - - '@rsbuild/core@2.0.15': - resolution: {integrity: sha512-O8vmMhZu1YImO6jOqt/K/vlJSvkq7UtSq5YM1DIlcEd9LW8Gf6/dkQ1B2KPI6F+hSMFBnTTTumdcIowSLCw97g==} - engines: {node: ^20.19.0 || >=22.12.0} - hasBin: true - peerDependencies: - core-js: '>= 3.0.0' - peerDependenciesMeta: - core-js: - optional: true - - '@rsbuild/core@2.1.0': - resolution: {integrity: sha512-BNOp22xLGA+L8zvZ12Qg/3zhFhWFZCvZ7OcQRoGLSTw1pB9q/XDLK+WGey9SFPOtsRD3CRPXheXApxwvneH6uA==} + '@rsbuild/core@2.1.5': + resolution: {integrity: sha512-7TW4U1SH7VxQZzSTIOzvwj5lo9uNTmGpsmTXFr4axQAE4giLDKP3kVUA1ZW4P3/Mz4QQJJyvZP29mVcb8kZCfg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -4588,196 +4543,83 @@ packages: '@rsdoctor/utils@1.5.16': resolution: {integrity: sha512-aFhv9gzDjJ5qyODO1Uno1NAfl/7WDhmJASJ5lQj1Qo8FV1VgtnYKFbbYdQYSpsowhxgklNISxVs905HdiBp6yg==} - '@rslib/core@0.22.1': - resolution: {integrity: sha512-RaqTITHFkpMDJG9fmD7Hu6FLE64hwctCo46asHOD2DipzQJWawg6K0pFGimTAyutYEZysIUfYgCwSYkbctDudg==} + '@rslib/core@0.23.2': + resolution: {integrity: sha512-KxSp+/y0BJ1O4oKwxX4ydBY7/ZVeJCUpWAmQniCIct8mTxIQFPGO/ibKbKq2IxZYqRuRpM8g+Dtyq0VbEQf9HQ==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: '@microsoft/api-extractor': ^7 - typescript: ^5 || ^6 + typescript: ^5 || ^6 || ^7.0.1-0 peerDependenciesMeta: '@microsoft/api-extractor': optional: true typescript: optional: true - '@rspack/binding-darwin-arm64@1.7.12': - resolution: {integrity: sha512-rbFprJaJiqrmfy8SHth8EsoRS0wg4bXcucwj9NiMzpGFq14Opw8c04iQ6H9BECYzgmN0PKZ9rh41LdVvhdZe4A==} + '@rspack/binding-darwin-arm64@2.1.3': + resolution: {integrity: sha512-oOGI0RSL89Ehu9T22rugmfUY9OC2eBqLMeWRYsu7bhlUrjoXeVfGBBSEXCse666BQ1sAiM8hD/k7nqVria/okQ==} cpu: [arm64] os: [darwin] - '@rspack/binding-darwin-arm64@2.0.8': - resolution: {integrity: sha512-vCgbgH7B7qom+uID+RCZsTCOYFb9wC4/4+1U6rMfytrXGVJ72eNQs2tbdjOl0lb18CT3N/n+VkWynUiLk84GwA==} - cpu: [arm64] - os: [darwin] - - '@rspack/binding-darwin-arm64@2.1.0': - resolution: {integrity: sha512-1DdnXLCl4/7BydtxvFyJbqOyvo3dgeKIdukr5BrM7UUA5rJnpin0qZIq/C0Y+ZwTx7ML4zdYaJeR+WOujRQH1Q==} - cpu: [arm64] - os: [darwin] - - '@rspack/binding-darwin-x64@1.7.12': - resolution: {integrity: sha512-jnOp+/UXOJa9xqUb8KXH03sysoO2e4Ij6tw6MqDdmdj8n/A8PQENRPUbW9AwXpPtVDJPus9r4fi7b3+6e4B8Hg==} - cpu: [x64] - os: [darwin] - - '@rspack/binding-darwin-x64@2.0.8': - resolution: {integrity: sha512-satPm2PD4B7jDTVlVAdvMVdUszwLvWUEnUDzLb77mvVkezKNDZmuhb+e8s+FfKs8hJpNbZ9VAejuA2rr8o985w==} + '@rspack/binding-darwin-x64@2.1.3': + resolution: {integrity: sha512-sVqWXNiFTMXAyN362y6IA+eJc8LXZKfHdhEJ/zDuMmRp+u2IvhgaF8tk3vX/OmeB9jydVjySijuiqk8No/FoCA==} cpu: [x64] os: [darwin] - '@rspack/binding-darwin-x64@2.1.0': - resolution: {integrity: sha512-PJB6n/BaupvfLaErsfvC7q9W07WozkPe2Xw7sQqX6fblK+4tooBp0ZdAtKi76L+U2fR8t8/nQb0Jokco0co7Fg==} - cpu: [x64] - os: [darwin] - - '@rspack/binding-linux-arm64-gnu@1.7.12': - resolution: {integrity: sha512-C8owWG+yvo7X0oVLIXetkoJhIFBP1LYNcAQqtgLmJnQLQDklGuP83dKC+zISGQWpjawHfZ1ER96vLgoTrxKZdw==} - cpu: [arm64] - os: [linux] - - '@rspack/binding-linux-arm64-gnu@2.0.8': - resolution: {integrity: sha512-pSI+npPQE/uDtiboqvcOIRJbEV2+B+H1xffmko/gw50la92oTUW60kVULFwsb6L0+GVCzIcwX3yq60GtYIn+Ug==} - cpu: [arm64] - os: [linux] - - '@rspack/binding-linux-arm64-gnu@2.1.0': - resolution: {integrity: sha512-TCmWIeI03ZZi8GjpIS2yl9JpaazsaA4F84zbX6a4kdZnFkrmFKRdvczZrquTNQvmggAEaJiPxkSrS8OC1LSAwA==} - cpu: [arm64] - os: [linux] - - '@rspack/binding-linux-arm64-musl@1.7.12': - resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==} + '@rspack/binding-linux-arm64-gnu@2.1.3': + resolution: {integrity: sha512-aCy9Zli/2Qf+Ee5otXfFQ6mhv5fEyn0wIoBVmouqtJoqOO21et6UTtJ+LHLsMDolwGLyHERAljeSFSmYX3/O5A==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@2.0.8': - resolution: {integrity: sha512-igjJ43yxWQ72GZqjDDZSSHax9/Vg+6rLMmOvFglTJUkQpB4Tyvu/YjW+WRjYj2xRw6blOjLxUSJWASvuSqqlvg==} + '@rspack/binding-linux-arm64-musl@2.1.3': + resolution: {integrity: sha512-flIE7eluz0d21Fn28EVm3vPwoJooOSqtmjLFVSuOMcoCbwV9clfor195oIrAppp/W7dL/3XquFuVfrsa01Jy8Q==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@2.1.0': - resolution: {integrity: sha512-HJzw5gG62qjj9fRQgj948naLucwE1Vg1bfcYHAxOr1/bVVIm4I4QvWGuqvd3XOu0MfLXPWvEyMAvJL+rtgamsw==} - cpu: [arm64] - os: [linux] - - '@rspack/binding-linux-riscv64-gnu@2.1.0': - resolution: {integrity: sha512-B3ENZHIBi5u1Apt6RJ62QSCabCijI5l86Sm2AEDYpQnqqBj3vIc+Br9HJHvNjK8PNWs1WfmD//UTUmQqZbYpKQ==} + '@rspack/binding-linux-riscv64-gnu@2.1.3': + resolution: {integrity: sha512-yojg8elye1nhsNeGncw0NrZ4pMGF7NVebR80CLg72TXyzfYwFJlFTdU5yUYb1Gy+JXIvrSCwzQt2QkyiEvmkfg==} cpu: [riscv64] os: [linux] - '@rspack/binding-linux-riscv64-musl@2.1.0': - resolution: {integrity: sha512-Qho1S8bW2BKRsJjl/f39GoyPRznF8ZarIgxZdVCIkn4k+3veggKWxqR1WWKoMj/LfykQd1uG3FF6n7zy5IfxWw==} + '@rspack/binding-linux-riscv64-musl@2.1.3': + resolution: {integrity: sha512-6PvbXb3FOK4X3S5QGvoSW/sqExmsvAoPnQ/YSFrXvTphkXFezA7wnobmGBHT8JQP31hcFRzJHIZSIOKktzSzzg==} cpu: [riscv64] os: [linux] - '@rspack/binding-linux-x64-gnu@1.7.12': - resolution: {integrity: sha512-MSos0FuPEefqo9V92ULd5hggKG29EkSNg1zDcypy0OkpsKh5pfjVxTLYFXgTcVyFoUQQbdG8zFBzYbwmJ8V4ew==} - cpu: [x64] - os: [linux] - - '@rspack/binding-linux-x64-gnu@2.0.8': - resolution: {integrity: sha512-zrkoEOnqj1hOEBO5T2I/2Ts2HSJsYFh1qXwMpK4dMJFGGNWDfNeUa6/LF5uq3VINF3JUl7RL47AgrucoSZJXPA==} + '@rspack/binding-linux-x64-gnu@2.1.3': + resolution: {integrity: sha512-lMXjoGKf0SnviH596fmTszgtnXLHmWOoE90G8grG9MvKVa3pelRmfps5ewZL9s8ENf3NXRfOxIhIf/M9as6MqA==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-gnu@2.1.0': - resolution: {integrity: sha512-oE2CMALLdV3QNiA3YYDZ46tDGf+WRlqu/tQ+B79JYKVwt3sI0fpzvgwPNpx/gfRKUyA0phaeYS4kyOEnpltjpA==} + '@rspack/binding-linux-x64-musl@2.1.3': + resolution: {integrity: sha512-0esT35v7pW2ZsJTMc/zDUHwpNXlPqyUCyuiLJvrAAUcdENrgOVe4DmFrgVJ2hwqI4GjeN1VBnGRJ8c+edAHH5w==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@1.7.12': - resolution: {integrity: sha512-JcAMVKXOnjfpC3coWjCFPWD3Yl8RBw6a+IXQQ8mfRlHaHMIiOv8IfZqx15XRxMUn49CtP7Z0Na8iiAg2aKrcfw==} - cpu: [x64] - os: [linux] - - '@rspack/binding-linux-x64-musl@2.0.8': - resolution: {integrity: sha512-6CtDaGZjNDvJd9TBp7a9zABbrPORO21W96+3ZcGBn0YNUPUk4ARxIxrTTpeJ/1F41QDM8AYIkGDdqEYMqTYBsA==} - cpu: [x64] - os: [linux] - - '@rspack/binding-linux-x64-musl@2.1.0': - resolution: {integrity: sha512-lxTFZgsfPPyyIt/DpOH5TK2u1ZROMB+gLp/LWvYBc8FSOtmR0Gl4L/AWmJdM2yqwPfy0hgSkVicf/7k80jHuVQ==} - cpu: [x64] - os: [linux] - - '@rspack/binding-wasm32-wasi@1.7.12': - resolution: {integrity: sha512-n+ZqP6ZMc0nhOgvadg5VhEs9ojtbES80AcWeFnmGkbzIszvGSO63GKNiRkXtjJ9KFuRzytbbmsCqkUVH+Tywxg==} - cpu: [wasm32] - - '@rspack/binding-wasm32-wasi@2.0.8': - resolution: {integrity: sha512-Yf4SiqTUroT5Ju+te0YAY2xxKOb35tECsO21v7hYyGa705wrgoAK/MmF7enOvs9GR1iZIqgiLD/wxsIxl8GjJw==} + '@rspack/binding-wasm32-wasi@2.1.3': + resolution: {integrity: sha512-UsrDjD59UEP0mhfN/Z+uTc3vLgiUvIr+mn92WC1sbQi9gtZohTYvaQYFhWuMkBqsACGcmZp704JAbbSrVrVYCA==} cpu: [wasm32] - '@rspack/binding-wasm32-wasi@2.1.0': - resolution: {integrity: sha512-ZsDDduXaEF1SpyGz2OFuEU9Tzm0pKtbtCYviymiNtQS+3lx6rXyv+FaK0oIWn+gWL+gVNamplxKnNNR2jZsp5w==} - cpu: [wasm32] - - '@rspack/binding-win32-arm64-msvc@1.7.12': - resolution: {integrity: sha512-8+h5fYDXYdmugbdfZ+D1y8IQ3rv2EhSfyGP7vBe+bjNyaMa4jWrpucmZbtxojUL1AzaeuHbvMdj9UO/gelk/+g==} - cpu: [arm64] - os: [win32] - - '@rspack/binding-win32-arm64-msvc@2.0.8': - resolution: {integrity: sha512-8NCuiQsAhXrwRBy57QZoypqrws/zLBkaQVGiB8hksr6v++8hNigNjqpQARLbd0iyMuHsQQ++8+auGk6xlDXmzw==} + '@rspack/binding-win32-arm64-msvc@2.1.3': + resolution: {integrity: sha512-42RS/SwKBTkNvXIPZXqTn0yEFN8zwGRfRe/ly0GDvPp/KxpLMFWxJmLxgtoLompU+0UCGvV4KpcBENt3oWs6BA==} cpu: [arm64] os: [win32] - '@rspack/binding-win32-arm64-msvc@2.1.0': - resolution: {integrity: sha512-0uMWAZYgwdkk0ocE4X85w/0BNWT5GaKJTEZDVYxfSYcfVAxJvIsuM0VH/cjRjsQtEeE1rcY7JvJyd0rQ6j0DqA==} - cpu: [arm64] - os: [win32] - - '@rspack/binding-win32-ia32-msvc@1.7.12': - resolution: {integrity: sha512-cDMGwTRSa2p9fNBVe1wTRkF2AEXZ9ARWW36QeC5CkLaI0Ezz8lvhF2+CSOPnhaQ1O1qtn0L0SF+lFnrY+I7xGQ==} + '@rspack/binding-win32-ia32-msvc@2.1.3': + resolution: {integrity: sha512-thk43H1JHHbetNF3txcsGXeOwZi2m6Luf/uVUqNORXjxr5VV8woHAgaAx4QXVZRg70z1VDjd8mBWnHBnKI0FGA==} cpu: [ia32] os: [win32] - '@rspack/binding-win32-ia32-msvc@2.0.8': - resolution: {integrity: sha512-bxiekytbX7V9KFAra+HkwtNWC6pYfHEBBZFpiT0xUs3mCFOmAAFVBsBSQsoCP9AdCEXoMAvNdnrHNw3iov4OZw==} - cpu: [ia32] - os: [win32] - - '@rspack/binding-win32-ia32-msvc@2.1.0': - resolution: {integrity: sha512-MRuIZwF6w1tGyZgoJZ5dnpLaD/oMx8zAYSYQfNS7l0f7qjxbnp42625wkeNB8kPqrmDfqaWUWLwiOaRqFPmumA==} - cpu: [ia32] - os: [win32] - - '@rspack/binding-win32-x64-msvc@1.7.12': - resolution: {integrity: sha512-wIqFvlgFqrgUyj/6S/FJcvShnkZOmIeXTfqvheLY67MGq8qd8jb1YimQVKAIrmWB3yuJKUFACI3Ag1UBtEedEA==} + '@rspack/binding-win32-x64-msvc@2.1.3': + resolution: {integrity: sha512-ObaUcj+BHo/aBL1weyM3orApaHyAR5Phr3YNEpQEifxjZbNKM1iO5X5prN4OqEv3H+7o5e/Wh9Fy3N7Vvd+psA==} cpu: [x64] os: [win32] - '@rspack/binding-win32-x64-msvc@2.0.8': - resolution: {integrity: sha512-7zPs8YCe/ZVJTwd+5lpB0CP0tkn2pONf/T1ycmVY76u21Nrwt8mXQGc/2yH2eWP4B7fikYBr3hGr7mpR2fajqQ==} - cpu: [x64] - os: [win32] - - '@rspack/binding-win32-x64-msvc@2.1.0': - resolution: {integrity: sha512-Fme2Ifa647CtD7N6we9xvK+COzfzVJREtUayxdG+VArPdijURZyRQVUKKlYSBW+2qMg+G+kF1xo7gf7svG3sNA==} - cpu: [x64] - os: [win32] - - '@rspack/binding@1.7.12': - resolution: {integrity: sha512-f4HHuLbvuld8Ba4iB/4ibse5XrKxFrgmM3S4P2AOKnPlekAFlBjmltCuaTL/W2ggYvILaVY+YcFXrEH1rrKeQA==} - - '@rspack/binding@2.0.8': - resolution: {integrity: sha512-3uZ+y8aQxq33ty2srMxg2Nu0XuBI6vVrG50rkDaXqwWqOohfgGUSfFuQK7EnSUNy4aFUQlCG6NHialQHJov0wg==} + '@rspack/binding@2.1.3': + resolution: {integrity: sha512-4UGXJqUHmm36tWG1GgFZz3p8sQ5JuSgWI+gq1xPPoihS41uYJL3cXuJnirTeWsmVrusmYZTQhgU3tl3VYGcJYg==} - '@rspack/binding@2.1.0': - resolution: {integrity: sha512-LsXFIOOYDutHk44SAOcVQa5iA7lhYwEbD+nZhgmCiGJvKKh0UIpBj6EAsBsB6omEK5GEXvjDeLFieKgbYW08QQ==} - - '@rspack/core@1.7.12': - resolution: {integrity: sha512-6CwFIHlhRmXfZoMj3v9MZ1SMTPBn+cHVXeMIeaGp5sufqinKsISbsqHu6ZMJu2wDSmZLdmQJX6zLxkhcAUlhkQ==} - engines: {node: '>=18.12.0'} - peerDependencies: - '@swc/helpers': '>=0.5.1' - peerDependenciesMeta: - '@swc/helpers': - optional: true - - '@rspack/core@2.0.8': - resolution: {integrity: sha512-+NLGJf8gZxihDmMFzjlly3toc2SMjeDmuvz0/Cai9AMdV4F+Pqcnt2BA9V4e3SY2jmhJQtPwgyyLtR1RiJO77g==} + '@rspack/core@2.1.3': + resolution: {integrity: sha512-1iGnxLrP+iyY0ZSjLZeQTaxrISpQz4yLyqJPmaF/l4uw27/dBcrloszAeLOJQ9jiv7EJtU0T5zB+LOFPpivIxA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@module-federation/runtime-tools': ^0.24.1 || ^2.0.0 @@ -4788,24 +4630,6 @@ packages: '@swc/helpers': optional: true - '@rspack/core@2.1.0': - resolution: {integrity: sha512-dlZRzWQi90HzLYErGh0/xnEWAEMEAtDKXvNxERCEj5uIVIOVu9+uYwpNyAkKc9cK5sPhOz05kk9MIb1EaUJ5gg==} - engines: {node: ^20.19.0 || >=22.12.0} - peerDependencies: - '@module-federation/runtime-tools': ^0.24.1 || ^2.0.0 - '@swc/helpers': ^0.5.23 - peerDependenciesMeta: - '@module-federation/runtime-tools': - optional: true - '@swc/helpers': - optional: true - - '@rspack/lite-tapable@1.1.0': - resolution: {integrity: sha512-E2B0JhYFmVAwdDiG14+DW0Di4Ze4Jg10Pc4/lILUrd5DRCaklduz2OvJ5HYQ6G+hd+WTzqQb3QnDNfK4yvAFYw==} - - '@rspack/lite-tapable@1.1.2': - resolution: {integrity: sha512-1OnyWChLGE46YzWyjlmYJssOu/Y0STAnnr2ueKPqDCYTf63GJMs0mxNnCul4dNiVqHYPKv3/fxrTY3IpqoVwZQ==} - '@rspack/plugin-react-refresh@2.0.2': resolution: {integrity: sha512-dGNZiCxQxgAUI9sah7gd8u+O7OJZRCmqtEJNDOd8xW5RqcieC86F7p5qcShyw6onH5pKf57evpr2VjGbaFGkZg==} peerDependencies: @@ -4868,12 +4692,12 @@ packages: '@rspack/resolver@0.2.8': resolution: {integrity: sha512-FBWqdHhzS8mcf/WN4Ktzr7EaeaN+hsxbN98EweegX3924beZuY6H70CSFWCv1fIHAieCUv/9XCjKggHvhCsLwA==} - '@rstest/core@0.8.1': - resolution: {integrity: sha512-7d/2fm2V91pVx/rRtZ2gl6Zh4hVMivtDl4RgHFhBOrxi//UwhKISeF5gS/CSwpCgfOf10TzJRXqdI17ueUBNMQ==} - engines: {node: '>=18.12.0'} + '@rstest/core@0.11.0': + resolution: {integrity: sha512-buy6EV9R6d0O9WMOSG0C91jwMcNYDw4Q0uFQNuwPpQLH85rTlVyuUM7EnEnvVGv5lG6dpgGwNTdRWx6mvWybag==} + engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: - happy-dom: '*' + happy-dom: ^20.8.3 jsdom: '*' peerDependenciesMeta: happy-dom: @@ -4881,10 +4705,10 @@ packages: jsdom: optional: true - '@rstest/coverage-istanbul@0.2.0': - resolution: {integrity: sha512-ghFY2XkjL2PFarLaG+BxFTJYbVXtAtcqW5rjOqheiOYV6PqlOHFf/s+fLkKeOTc1oVoL3A/9vjMBc8fOgjAF/A==} + '@rstest/coverage-istanbul@0.11.0': + resolution: {integrity: sha512-WeQ8NPDNWFdv5THtncsii7vk+8cKECLfn15yuk6KT+OXNGn5Pz1raLX/tdQPz0qsB/rI2Zo65wiOvk5ktD7PYg==} peerDependencies: - '@rstest/core': ~0.8.0 + '@rstest/core': ^0.11.0 '@sec-ant/readable-stream@0.4.1': resolution: {integrity: sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg==} @@ -5523,6 +5347,9 @@ packages: '@types/node@25.0.10': resolution: {integrity: sha512-zWW5KPngR/yvakJgGOmZ5vTBemDoSqF3AcV/LrO5u5wTWyEAVVh+IT39G4gtyAkh3CtTZs8aX/yRM82OfzHJRg==} + '@types/node@25.9.5': + resolution: {integrity: sha512-OScDchr2fwuUmWdf4kZ9h7PcJiYDVInhJizG/biAq3cAvqwYktuy/TYGGdZNMtNTFUP7rnb0NU4TUdm82kt4Rg==} + '@types/pegjs@0.10.6': resolution: {integrity: sha512-eLYXDbZWXh2uxf+w8sXS8d6KSoXTswfps6fvCUuVAGN8eRpfe7h9eSRydxiSJvo9Bf+GzifsDOr9TMQlmJdmkw==} @@ -6228,6 +6055,11 @@ packages: engines: {node: '>=6.0.0'} hasBin: true + baseline-browser-mapping@2.10.42: + resolution: {integrity: sha512-c/jurFrDLyui7o1J86yLkRu4LMsTYcBohveus7/I2Hzdn9KIP2bdJPTue/lR1KH46enoPbD77GKeSYNdyPoD3Q==} + engines: {node: '>=6.0.0'} + hasBin: true + basic-auth@2.0.1: resolution: {integrity: sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==} engines: {node: '>= 0.8'} @@ -6317,6 +6149,11 @@ packages: engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + browserslist@4.28.5: + resolution: {integrity: sha512-Cu2E6QejHWzuDMTkuwgpABFgDfZrXLQq5V13YOACZx4mFAG4IwGTbTfHPMr4WtxlHoXSM8FIuRwYYCz5XiabaQ==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + buffer-from@1.1.2: resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} @@ -6369,6 +6206,9 @@ packages: caniuse-lite@1.0.30001799: resolution: {integrity: sha512-hG1bReV+OUU+MOqK4t/ZWI0tZOyz3rqS9XuhOUz1cIcbwBKjOyJEJuw9ER5JuNyqxNk8u/JUVbGibBOL1yrjFw==} + caniuse-lite@1.0.30001803: + resolution: {integrity: sha512-g/uHREV2ZpK9qMalCsWaxmA6ol+DX8GYhuf3T40RKoP+oL7vhRJh8LNt73PCjpnR6l14FzfPrB5Yux4PKm2meg==} + chain-function@1.0.1: resolution: {integrity: sha512-SxltgMwL9uCko5/ZCLiyG2B7R9fY4pDZUw7hJ4MhirdjBLosoDqkWABi3XMucddHdLiFJMb7PD2MZifZriuMTg==} @@ -6872,6 +6712,9 @@ packages: electron-to-chromium@1.5.380: resolution: {integrity: sha512-W6d5AbuEoRayO447cqrg6lKJIlscgRnnxOZl/08kfV71BQDoEBC7Wwis68z87LjyK6f4kWyTaubuDbhHKrZkbA==} + electron-to-chromium@1.5.389: + resolution: {integrity: sha512-cEto7aeOqBfU1D+c5py5pE+ooscKE75JifxLBdFUZsqAxRS6y7kebtxAZvICszSl05gPjYHDTjY+lXpyGvpJbg==} + emoji-regex@8.0.0: resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} @@ -6907,8 +6750,8 @@ packages: resolution: {integrity: sha512-aNnGCvbJ/RIyWo1IuhNdVjnNF+EjH9wpzpNHt+ci/m9He9LJvUN8wrCcXjp9cWsGNAuvSpVFTx/vraAFQ8qGjQ==} engines: {node: '>=10.13.0'} - enhanced-resolve@5.24.1: - resolution: {integrity: sha512-7DdUaTjmNwMcH2gLr1qycesKII3BK4RLy/mdAb7x10Lq7bR4aNKHt1BR1ZALSv0rPM/hF5wYF0PhGop/rJm8vw==} + enhanced-resolve@5.24.2: + resolution: {integrity: sha512-rpsZEGT1jFuve6QlpyRp9ckQ+kN61hvF9BzCPyMdaKTm8UJce96KBn3sorXOFXlzjPrs3Vc4T1NsSroZ3PxlFw==} engines: {node: '>=10.13.0'} enquirer@2.4.1: @@ -6971,6 +6814,9 @@ packages: es-module-lexer@2.1.0: resolution: {integrity: sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==} + es-module-lexer@2.3.0: + resolution: {integrity: sha512-KLdwQm2NvGLDkQDCGvmiQrhkd0JbMzXthwQAUgWjQuQdBLFa3eiBP5arXZyA+f8x+x7OXgud6bq2rxjGtHV2tw==} + es-object-atoms@1.1.2: resolution: {integrity: sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==} engines: {node: '>= 0.4'} @@ -9403,14 +9249,14 @@ packages: resolution: {integrity: sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==} engines: {node: '>= 18'} - rsbuild-plugin-dts@0.22.1: - resolution: {integrity: sha512-6vBfXgwK4j6GkjSRH13tuceBavc6qwSE5IVSoVCZ/wRuM0ZL7dIjdk+yGSWKJt5lNMfc4XwQoTErGIC9zhgztQ==} + rsbuild-plugin-dts@0.23.2: + resolution: {integrity: sha512-Ve8WOSPyTBjxH40O/6fChJtflL7yqcUtt5zbF0eHDM4hIt35jqLocRlSdCxFJdQm0blTjl6+hkmPa/vNI06ArA==} engines: {node: ^20.19.0 || >=22.12.0} peerDependencies: '@microsoft/api-extractor': ^7 '@rsbuild/core': ^1.0.0 || ^2.0.0-0 '@typescript/native-preview': ^7.0.0-0 - typescript: ^5 || ^6 + typescript: ^5 || ^6 || ^7.0.1-0 peerDependenciesMeta: '@microsoft/api-extractor': optional: true @@ -9612,14 +9458,14 @@ packages: resolution: {integrity: sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==} engines: {node: '>= 18'} - seroval-plugins@1.5.4: - resolution: {integrity: sha512-S0xQPhUTefAhNvNWFg0c1J8qJArHt5KdtJ/cFAofo06KD1MVSeFWyl4iiu+ApDIuw0WhjpOfCdgConOfAnLgkw==} + seroval-plugins@1.5.5: + resolution: {integrity: sha512-+BDhqYM6CEn3x09v44dpa9p6974FuUB2dxk+Ctn04k0cO1Zt6QODTXfmEZK0eBaTe/fJBvP4NMGuNJ+R8T+QMg==} engines: {node: '>=10'} peerDependencies: seroval: ^1.0 - seroval@1.5.4: - resolution: {integrity: sha512-46uFvgrXTVxZcUorgSSRZ4y+ieqLLQRMlG4bnCZKW3qI6BZm7Rg4ntMW4p1mILEEBZWrFlcpp0AyIIlM6jD9iw==} + seroval@1.5.5: + resolution: {integrity: sha512-bSjOuPcwPKLSJNhr9+bZxA20nQxVle5J5MNsYRVE6cIg7KpRLXGupymePavu0jrxlPiPsr4xGZSB8yUY2sH2sw==} engines: {node: '>=10'} serve-handler@6.1.7: @@ -9989,8 +9835,8 @@ packages: resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==} engines: {node: '>=8'} - terser@5.48.0: - resolution: {integrity: sha512-J/9An6vs9Us6wKRriSFXBWdRZapREHqFzdNUKk0pmu804EMR6dr6winwo7e5JDxN4xahxQsuysyYFwlwj4XN/Q==} + terser@5.49.0: + resolution: {integrity: sha512-SNiDnXyHSrxVcIOtVbULzcTmniUiwcV7Nwdyj1twVubeTmbjoa8p69KKDpfkdoOavuM4/GRm1+ykI8qqnavHoA==} engines: {node: '>=10'} hasBin: true @@ -10001,10 +9847,6 @@ packages: resolution: {integrity: sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==} engines: {node: '>=12.0.0'} - tinypool@1.1.1: - resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==} - engines: {node: ^18.0.0 || >=20.0.0} - tldts-core@7.4.5: resolution: {integrity: sha512-pGrwzZDvPwKe+7NNUqAunb6rqTfynr0VOUhCMdqbu5xlvNiszsAJygRzwvpVycdzejlbpY+SWJOn+s75Og7FEA==} @@ -10153,6 +9995,9 @@ packages: undici-types@7.16.0: resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + undici-types@7.24.6: + resolution: {integrity: sha512-WRNW+sJgj5OBN4/0JpHFqtqzhpbnV0GuB+OozA9gCL7a993SmU+1JBZCzLNxYsbMfIeDL+lTsphD5jN5N+n0zg==} + undici@7.24.7: resolution: {integrity: sha512-H/nlJ/h0ggGC+uRL3ovD+G0i4bqhvsDOpbDv7At5eFLlj2b41L8QliGbnl2H7SnDiYhENphh1tQFJZf+MyfLsQ==} engines: {node: '>=20.18.1'} @@ -10347,6 +10192,10 @@ packages: resolution: {integrity: sha512-HPuy+uuoTCaaoEoI1LQ3JN9+vrPBvEesnnX1jADHy728cHSMlq4wUc4afYqahq2B1mhQVZxCXOkNTnXltr+2vQ==} engines: {node: '>=10.13.0'} + webpack-sources@3.5.1: + resolution: {integrity: sha512-jyuiGJdtvY434z5bUZrjz67v76/ePNvFZTp9Mdz29IlH4+GPsgyGjiv0fKI+M7BdkU6ADjulUcKAd3tUK3WlEw==} + engines: {node: '>=10.13.0'} + webpack-virtual-modules@0.5.0: resolution: {integrity: sha512-kyDivFZ7ZM0BVOUteVbDFhlRt7Ah/CSPwJdi8hBpkK7QLumUqdLtVfm/PX/hkcnrvr0i77fO5+TjZ94Pe+C9iw==} @@ -11173,6 +11022,11 @@ snapshots: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.1': dependencies: tslib: 2.8.1 @@ -11613,7 +11467,7 @@ snapshots: '@img/sharp-wasm32@0.34.5': dependencies: - '@emnapi/runtime': 1.11.1 + '@emnapi/runtime': 1.11.2 optional: true '@img/sharp-win32-arm64@0.34.5': @@ -11769,7 +11623,7 @@ snapshots: - node-fetch - utf-8-validate - '@module-federation/enhanced@2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16))': + '@module-federation/enhanced@2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16))': dependencies: '@module-federation/bridge-react-webpack-plugin': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/cli': 2.5.1(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3) @@ -11778,7 +11632,7 @@ snapshots: '@module-federation/inject-external-runtime-core-plugin': 2.5.1(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13))) '@module-federation/managers': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/manifest': 2.5.1(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3) - '@module-federation/rspack': 2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3) + '@module-federation/rspack': 2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3) '@module-federation/runtime-tools': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/sdk': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/webpack-bundler-runtime': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) @@ -11794,8 +11648,6 @@ snapshots: - node-fetch - utf-8-validate - '@module-federation/error-codes@0.22.0': {} - '@module-federation/error-codes@2.5.1': {} '@module-federation/inject-external-runtime-core-plugin@2.5.1(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))': @@ -11822,9 +11674,9 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/node@2.7.44(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16))': + '@module-federation/node@2.7.44(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16))': dependencies: - '@module-federation/enhanced': 2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + '@module-federation/enhanced': 2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@module-federation/runtime': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/sdk': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) encoding: 0.1.13 @@ -11839,13 +11691,13 @@ snapshots: - utf-8-validate - vue-tsc - '@module-federation/rsbuild-plugin@2.5.1(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16))': + '@module-federation/rsbuild-plugin@2.5.1(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16))': dependencies: - '@module-federation/enhanced': 2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) - '@module-federation/node': 2.7.44(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + '@module-federation/enhanced': 2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) + '@module-federation/node': 2.7.44(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(typescript@5.9.3)(webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16)) '@module-federation/sdk': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) transitivePeerDependencies: - '@rspack/core' - bufferutil @@ -11855,7 +11707,7 @@ snapshots: - vue-tsc - webpack - '@module-federation/rspack@2.5.1(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)': + '@module-federation/rspack@2.5.1(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/dts-plugin': 2.5.1(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3) @@ -11864,7 +11716,7 @@ snapshots: '@module-federation/manifest': 2.5.1(node-fetch@2.7.0(encoding@0.1.13))(typescript@5.9.3) '@module-federation/runtime-tools': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@module-federation/sdk': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -11872,11 +11724,6 @@ snapshots: - node-fetch - utf-8-validate - '@module-federation/runtime-core@0.22.0': - dependencies: - '@module-federation/error-codes': 0.22.0 - '@module-federation/sdk': 0.22.0 - '@module-federation/runtime-core@2.5.1(node-fetch@2.7.0(encoding@0.1.13))': dependencies: '@module-federation/error-codes': 2.5.1 @@ -11884,11 +11731,6 @@ snapshots: transitivePeerDependencies: - node-fetch - '@module-federation/runtime-tools@0.22.0': - dependencies: - '@module-federation/runtime': 0.22.0 - '@module-federation/webpack-bundler-runtime': 0.22.0 - '@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13))': dependencies: '@module-federation/runtime': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) @@ -11896,12 +11738,6 @@ snapshots: transitivePeerDependencies: - node-fetch - '@module-federation/runtime@0.22.0': - dependencies: - '@module-federation/error-codes': 0.22.0 - '@module-federation/runtime-core': 0.22.0 - '@module-federation/sdk': 0.22.0 - '@module-federation/runtime@2.5.1(node-fetch@2.7.0(encoding@0.1.13))': dependencies: '@module-federation/error-codes': 2.5.1 @@ -11910,8 +11746,6 @@ snapshots: transitivePeerDependencies: - node-fetch - '@module-federation/sdk@0.22.0': {} - '@module-federation/sdk@2.5.1(node-fetch@2.7.0(encoding@0.1.13))': optionalDependencies: node-fetch: 2.7.0(encoding@0.1.13) @@ -11921,11 +11755,6 @@ snapshots: find-pkg: 2.0.0 resolve: 1.22.8 - '@module-federation/webpack-bundler-runtime@0.22.0': - dependencies: - '@module-federation/runtime': 0.22.0 - '@module-federation/sdk': 0.22.0 - '@module-federation/webpack-bundler-runtime@2.5.1(node-fetch@2.7.0(encoding@0.1.13))': dependencies: '@module-federation/error-codes': 2.5.1 @@ -11943,38 +11772,24 @@ snapshots: outvariant: 1.4.3 strict-event-emitter: 0.5.1 - '@napi-rs/wasm-runtime@1.0.7': - dependencies: - '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 - '@tybys/wasm-util': 0.10.3 - optional: true - - '@napi-rs/wasm-runtime@1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': dependencies: '@emnapi/core': 1.10.0 '@emnapi/runtime': 1.10.0 '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 '@tybys/wasm-util': 0.10.3 optional: true - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0)': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@tybys/wasm-util': 0.10.3 - optional: true - - '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': dependencies: '@emnapi/core': 1.11.1 - '@emnapi/runtime': 1.11.1 + '@emnapi/runtime': 1.11.2 '@tybys/wasm-util': 0.10.3 optional: true @@ -13021,7 +12836,7 @@ snapshots: optionalDependencies: typescript: 5.9.3 - '@react-router/dev@7.14.0(@react-router/serve@7.14.0(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@6.0.1-rc))(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@6.0.1-rc)(vite@7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': + '@react-router/dev@7.14.0(@react-router/serve@7.14.0(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@6.0.1-rc))(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@6.0.1-rc)(vite@7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': dependencies: '@babel/core': 7.29.0 '@babel/generator': 7.29.7 @@ -13051,8 +12866,8 @@ snapshots: semver: 7.8.5 tinyglobby: 0.2.17 valibot: 1.4.2(typescript@6.0.1-rc) - vite: 7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) - vite-node: 3.2.4(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) + vite-node: 3.2.4(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) optionalDependencies: '@react-router/serve': 7.14.0(react-router@7.14.0(react-dom@19.2.3(react@19.2.3))(react@19.2.3))(typescript@6.0.1-rc) typescript: 6.0.1-rc @@ -13072,7 +12887,7 @@ snapshots: - tsx - yaml - '@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': + '@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': dependencies: '@babel/core': 7.29.0 '@babel/generator': 7.29.7 @@ -13102,8 +12917,8 @@ snapshots: semver: 7.8.5 tinyglobby: 0.2.17 valibot: 1.4.2(typescript@5.9.3) - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) - vite-node: 3.2.4(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) + vite-node: 3.2.4(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) optionalDependencies: '@react-router/serve': 7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) typescript: 5.9.3 @@ -13123,7 +12938,58 @@ snapshots: - tsx - yaml - '@react-router/dev@8.0.1(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': + '@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': + dependencies: + '@babel/core': 7.29.0 + '@babel/generator': 7.29.7 + '@babel/parser': 7.29.7 + '@babel/plugin-syntax-jsx': 7.29.7(@babel/core@7.29.0) + '@babel/preset-typescript': 7.29.7(@babel/core@7.29.0) + '@babel/traverse': 7.29.7 + '@babel/types': 7.29.7 + '@react-router/node': 7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) + '@remix-run/node-fetch-server': 0.13.3 + arg: 5.0.2 + babel-dead-code-elimination: 1.0.12 + chokidar: 4.0.3 + dedent: 1.7.2 + es-module-lexer: 1.7.0 + exit-hook: 2.2.1 + isbot: 5.1.34 + jsesc: 3.0.2 + lodash: 4.18.1 + p-map: 7.0.4 + pathe: 1.1.2 + picocolors: 1.1.1 + pkg-types: 2.3.1 + prettier: 3.8.1 + react-refresh: 0.14.2 + react-router: 7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) + semver: 7.8.5 + tinyglobby: 0.2.17 + valibot: 1.4.2(typescript@5.9.3) + vite: 7.3.1(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) + vite-node: 3.2.4(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) + optionalDependencies: + '@react-router/serve': 7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3) + typescript: 5.9.3 + wrangler: 4.105.0(@cloudflare/workers-types@4.20260628.1) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + '@react-router/dev@8.0.1(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1))': dependencies: '@babel/core': 7.29.7 '@babel/generator': 7.29.7 @@ -13153,7 +13019,7 @@ snapshots: semver: 7.8.5 tinyglobby: 0.2.17 valibot: 1.4.2(typescript@5.9.3) - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) optionalDependencies: typescript: 5.9.3 wrangler: 4.105.0(@cloudflare/workers-types@4.20260628.1) @@ -13221,9 +13087,9 @@ snapshots: optionalDependencies: typescript: 5.9.3 - '@react-router/remix-routes-option-adapter@7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3)': + '@react-router/remix-routes-option-adapter@7.13.0(@react-router/dev@7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)))(typescript@5.9.3)': dependencies: - '@react-router/dev': 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) + '@react-router/dev': 7.18.0(@react-router/serve@7.18.0(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(typescript@5.9.3))(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))(wrangler@4.105.0(@cloudflare/workers-types@4.20260628.1)) optionalDependencies: typescript: 5.9.3 @@ -13376,33 +13242,16 @@ snapshots: '@rollup/rollup-win32-x64-msvc@4.62.2': optional: true - '@rsbuild/core@1.7.2': - dependencies: - '@rspack/core': 1.7.12(@swc/helpers@0.5.23) - '@rspack/lite-tapable': 1.1.2 - '@swc/helpers': 0.5.23 - core-js: 3.47.0 - jiti: 2.7.0 - - '@rsbuild/core@2.0.15(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)': + '@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)': dependencies: - '@rspack/core': 2.0.8(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) '@swc/helpers': 0.5.23 optionalDependencies: core-js: 3.47.0 transitivePeerDependencies: - '@module-federation/runtime-tools' - '@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)': - dependencies: - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) - '@swc/helpers': 0.5.23 - optionalDependencies: - core-js: 3.47.0 - transitivePeerDependencies: - - '@module-federation/runtime-tools' - - '@rsbuild/plugin-babel@2.0.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))': + '@rsbuild/plugin-babel@2.0.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))': dependencies: '@babel/core': 7.29.7 '@babel/plugin-proposal-decorators': 7.29.7(@babel/core@7.29.7) @@ -13411,11 +13260,11 @@ snapshots: '@types/babel__core': 7.20.5 reduce-configs: 1.1.2 optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) transitivePeerDependencies: - supports-color - '@rsbuild/plugin-check-syntax@1.6.1(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))': + '@rsbuild/plugin-check-syntax@1.6.1(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))': dependencies: acorn: 8.17.0 browserslist-to-es-version: 1.4.2 @@ -13423,30 +13272,30 @@ snapshots: picocolors: 1.1.1 source-map: 0.7.6 optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) - '@rsbuild/plugin-less@1.6.4(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsbuild/plugin-less@1.6.4(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: deepmerge: 4.3.1 less: 4.6.7 - less-loader: 12.3.3(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(less@4.6.7)(webpack@5.108.1(lightningcss@1.32.0)) + less-loader: 12.3.3(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(less@4.6.7)(webpack@5.108.1(lightningcss@1.32.0)) reduce-configs: 1.1.2 optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) transitivePeerDependencies: - '@rspack/core' - webpack - '@rsbuild/plugin-react@2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))': + '@rsbuild/plugin-react@2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))': dependencies: - '@rspack/plugin-react-refresh': 2.0.2(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(react-refresh@0.18.0) + '@rspack/plugin-react-refresh': 2.0.2(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(react-refresh@0.18.0) react-refresh: 0.18.0 optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) transitivePeerDependencies: - '@rspack/core' - '@rsbuild/plugin-sass@1.5.3(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))': + '@rsbuild/plugin-sass@1.5.3(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))': dependencies: deepmerge: 4.3.1 loader-utils: 2.0.4 @@ -13454,42 +13303,42 @@ snapshots: reduce-configs: 1.1.2 sass-embedded: 1.100.0 optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) - '@rsbuild/plugin-svgr@2.0.4(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(typescript@6.0.1-rc)': + '@rsbuild/plugin-svgr@2.0.4(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(typescript@6.0.1-rc)': dependencies: - '@rsbuild/plugin-react': 2.1.0(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) + '@rsbuild/plugin-react': 2.1.0(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)) '@svgr/core': 8.1.0(typescript@6.0.1-rc) '@svgr/plugin-jsx': 8.1.0(@svgr/core@8.1.0(typescript@6.0.1-rc)) '@svgr/plugin-svgo': 8.1.0(@svgr/core@8.1.0(typescript@6.0.1-rc))(typescript@6.0.1-rc) deepmerge: 4.3.1 loader-utils: 3.3.1 optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) transitivePeerDependencies: - '@rspack/core' - supports-color - typescript - '@rsbuild/plugin-tailwindcss@2.0.3(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsbuild/plugin-tailwindcss@2.0.3(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: - '@tailwindcss/webpack': 4.3.2(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@tailwindcss/webpack': 4.3.2(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) optionalDependencies: - '@rsbuild/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) transitivePeerDependencies: - '@rspack/core' - webpack '@rsdoctor/client@1.5.16': {} - '@rsdoctor/core@1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsdoctor/core@1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: - '@rsbuild/plugin-check-syntax': 1.6.1(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)) - '@rsdoctor/graph': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/sdk': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/types': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rspack/resolver': 0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@rsbuild/plugin-check-syntax': 1.6.1(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)) + '@rsdoctor/graph': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/sdk': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/types': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rspack/resolver': 0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) browserslist-load-config: 1.0.3 es-toolkit: 1.49.0 filesize: 11.0.19 @@ -13506,10 +13355,10 @@ snapshots: - utf-8-validate - webpack - '@rsdoctor/graph@1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsdoctor/graph@1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: - '@rsdoctor/types': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/types': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) es-toolkit: 1.49.0 path-browserify: 1.0.1 source-map: 0.7.6 @@ -13517,15 +13366,15 @@ snapshots: - '@rspack/core' - webpack - '@rsdoctor/rspack-plugin@1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsdoctor/rspack-plugin@1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: - '@rsdoctor/core': 1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)(@rsbuild/core@2.1.0(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/graph': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/sdk': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/types': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/core': 1.5.16(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/graph': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/sdk': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/types': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) optionalDependencies: - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -13535,12 +13384,12 @@ snapshots: - utf-8-validate - webpack - '@rsdoctor/sdk@1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsdoctor/sdk@1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: '@rsdoctor/client': 1.5.16 - '@rsdoctor/graph': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/types': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) - '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/graph': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/types': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/utils': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) launch-editor: 2.14.1 safer-buffer: 2.1.2 socket.io: 4.8.1 @@ -13552,20 +13401,20 @@ snapshots: - utf-8-validate - webpack - '@rsdoctor/types@1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsdoctor/types@1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: '@types/connect': 3.4.38 '@types/estree': 1.0.5 '@types/tapable': 2.3.0 source-map: 0.7.6 optionalDependencies: - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) webpack: 5.108.1(lightningcss@1.32.0) - '@rsdoctor/utils@1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@rsdoctor/utils@1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: '@babel/code-frame': 7.26.2 - '@rsdoctor/types': 1.5.16(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) + '@rsdoctor/types': 1.5.16(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0)) '@types/estree': 1.0.5 acorn: 8.17.0 acorn-import-attributes: 1.9.5(acorn@8.17.0) @@ -13583,10 +13432,10 @@ snapshots: - '@rspack/core' - webpack - '@rslib/core@0.22.1(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)(typescript@5.9.3)': + '@rslib/core@0.23.2(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0)(typescript@5.9.3)': dependencies: - '@rsbuild/core': 2.0.15(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0) - rsbuild-plugin-dts: 0.22.1(@rsbuild/core@2.0.15(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(typescript@5.9.3) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) + rsbuild-plugin-dts: 0.23.2(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(typescript@5.9.3) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -13594,184 +13443,73 @@ snapshots: - '@typescript/native-preview' - core-js - '@rspack/binding-darwin-arm64@1.7.12': - optional: true - - '@rspack/binding-darwin-arm64@2.0.8': - optional: true - - '@rspack/binding-darwin-arm64@2.1.0': + '@rspack/binding-darwin-arm64@2.1.3': optional: true - '@rspack/binding-darwin-x64@1.7.12': + '@rspack/binding-darwin-x64@2.1.3': optional: true - '@rspack/binding-darwin-x64@2.0.8': + '@rspack/binding-linux-arm64-gnu@2.1.3': optional: true - '@rspack/binding-darwin-x64@2.1.0': + '@rspack/binding-linux-arm64-musl@2.1.3': optional: true - '@rspack/binding-linux-arm64-gnu@1.7.12': + '@rspack/binding-linux-riscv64-gnu@2.1.3': optional: true - '@rspack/binding-linux-arm64-gnu@2.0.8': + '@rspack/binding-linux-riscv64-musl@2.1.3': optional: true - '@rspack/binding-linux-arm64-gnu@2.1.0': + '@rspack/binding-linux-x64-gnu@2.1.3': optional: true - '@rspack/binding-linux-arm64-musl@1.7.12': + '@rspack/binding-linux-x64-musl@2.1.3': optional: true - '@rspack/binding-linux-arm64-musl@2.0.8': - optional: true - - '@rspack/binding-linux-arm64-musl@2.1.0': - optional: true - - '@rspack/binding-linux-riscv64-gnu@2.1.0': - optional: true - - '@rspack/binding-linux-riscv64-musl@2.1.0': - optional: true - - '@rspack/binding-linux-x64-gnu@1.7.12': - optional: true - - '@rspack/binding-linux-x64-gnu@2.0.8': - optional: true - - '@rspack/binding-linux-x64-gnu@2.1.0': - optional: true - - '@rspack/binding-linux-x64-musl@1.7.12': - optional: true - - '@rspack/binding-linux-x64-musl@2.0.8': - optional: true - - '@rspack/binding-linux-x64-musl@2.1.0': - optional: true - - '@rspack/binding-wasm32-wasi@1.7.12': - dependencies: - '@napi-rs/wasm-runtime': 1.0.7 - optional: true - - '@rspack/binding-wasm32-wasi@2.0.8': - dependencies: - '@emnapi/core': 1.10.0 - '@emnapi/runtime': 1.10.0 - '@napi-rs/wasm-runtime': 1.1.4(@emnapi/core@1.10.0)(@emnapi/runtime@1.10.0) - optional: true - - '@rspack/binding-wasm32-wasi@2.1.0': + '@rspack/binding-wasm32-wasi@2.1.3': dependencies: '@emnapi/core': 1.11.1 '@emnapi/runtime': 1.11.1 - '@napi-rs/wasm-runtime': 1.1.5(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) - optional: true - - '@rspack/binding-win32-arm64-msvc@1.7.12': - optional: true - - '@rspack/binding-win32-arm64-msvc@2.0.8': - optional: true - - '@rspack/binding-win32-arm64-msvc@2.1.0': - optional: true - - '@rspack/binding-win32-ia32-msvc@1.7.12': - optional: true - - '@rspack/binding-win32-ia32-msvc@2.0.8': - optional: true - - '@rspack/binding-win32-ia32-msvc@2.1.0': + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) optional: true - '@rspack/binding-win32-x64-msvc@1.7.12': + '@rspack/binding-win32-arm64-msvc@2.1.3': optional: true - '@rspack/binding-win32-x64-msvc@2.0.8': + '@rspack/binding-win32-ia32-msvc@2.1.3': optional: true - '@rspack/binding-win32-x64-msvc@2.1.0': + '@rspack/binding-win32-x64-msvc@2.1.3': optional: true - '@rspack/binding@1.7.12': - optionalDependencies: - '@rspack/binding-darwin-arm64': 1.7.12 - '@rspack/binding-darwin-x64': 1.7.12 - '@rspack/binding-linux-arm64-gnu': 1.7.12 - '@rspack/binding-linux-arm64-musl': 1.7.12 - '@rspack/binding-linux-x64-gnu': 1.7.12 - '@rspack/binding-linux-x64-musl': 1.7.12 - '@rspack/binding-wasm32-wasi': 1.7.12 - '@rspack/binding-win32-arm64-msvc': 1.7.12 - '@rspack/binding-win32-ia32-msvc': 1.7.12 - '@rspack/binding-win32-x64-msvc': 1.7.12 - - '@rspack/binding@2.0.8': - optionalDependencies: - '@rspack/binding-darwin-arm64': 2.0.8 - '@rspack/binding-darwin-x64': 2.0.8 - '@rspack/binding-linux-arm64-gnu': 2.0.8 - '@rspack/binding-linux-arm64-musl': 2.0.8 - '@rspack/binding-linux-x64-gnu': 2.0.8 - '@rspack/binding-linux-x64-musl': 2.0.8 - '@rspack/binding-wasm32-wasi': 2.0.8 - '@rspack/binding-win32-arm64-msvc': 2.0.8 - '@rspack/binding-win32-ia32-msvc': 2.0.8 - '@rspack/binding-win32-x64-msvc': 2.0.8 - - '@rspack/binding@2.1.0': - optionalDependencies: - '@rspack/binding-darwin-arm64': 2.1.0 - '@rspack/binding-darwin-x64': 2.1.0 - '@rspack/binding-linux-arm64-gnu': 2.1.0 - '@rspack/binding-linux-arm64-musl': 2.1.0 - '@rspack/binding-linux-riscv64-gnu': 2.1.0 - '@rspack/binding-linux-riscv64-musl': 2.1.0 - '@rspack/binding-linux-x64-gnu': 2.1.0 - '@rspack/binding-linux-x64-musl': 2.1.0 - '@rspack/binding-wasm32-wasi': 2.1.0 - '@rspack/binding-win32-arm64-msvc': 2.1.0 - '@rspack/binding-win32-ia32-msvc': 2.1.0 - '@rspack/binding-win32-x64-msvc': 2.1.0 - - '@rspack/core@1.7.12(@swc/helpers@0.5.23)': - dependencies: - '@module-federation/runtime-tools': 0.22.0 - '@rspack/binding': 1.7.12 - '@rspack/lite-tapable': 1.1.0 - optionalDependencies: - '@swc/helpers': 0.5.23 - - '@rspack/core@2.0.8(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23)': - dependencies: - '@rspack/binding': 2.0.8 + '@rspack/binding@2.1.3': optionalDependencies: - '@module-federation/runtime-tools': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) - '@swc/helpers': 0.5.23 - - '@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)': - dependencies: - '@rspack/binding': 2.1.0 + '@rspack/binding-darwin-arm64': 2.1.3 + '@rspack/binding-darwin-x64': 2.1.3 + '@rspack/binding-linux-arm64-gnu': 2.1.3 + '@rspack/binding-linux-arm64-musl': 2.1.3 + '@rspack/binding-linux-riscv64-gnu': 2.1.3 + '@rspack/binding-linux-riscv64-musl': 2.1.3 + '@rspack/binding-linux-x64-gnu': 2.1.3 + '@rspack/binding-linux-x64-musl': 2.1.3 + '@rspack/binding-wasm32-wasi': 2.1.3 + '@rspack/binding-win32-arm64-msvc': 2.1.3 + '@rspack/binding-win32-ia32-msvc': 2.1.3 + '@rspack/binding-win32-x64-msvc': 2.1.3 + + '@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23)': + dependencies: + '@rspack/binding': 2.1.3 optionalDependencies: '@module-federation/runtime-tools': 2.5.1(node-fetch@2.7.0(encoding@0.1.13)) '@swc/helpers': 0.5.23 - '@rspack/lite-tapable@1.1.0': {} - - '@rspack/lite-tapable@1.1.2': {} - - '@rspack/plugin-react-refresh@2.0.2(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(react-refresh@0.18.0)': + '@rspack/plugin-react-refresh@2.0.2(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23))(react-refresh@0.18.0)': dependencies: react-refresh: 0.18.0 optionalDependencies: - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) '@rspack/resolver-binding-darwin-arm64@0.2.8': optional: true @@ -13791,9 +13529,9 @@ snapshots: '@rspack/resolver-binding-linux-x64-musl@0.2.8': optional: true - '@rspack/resolver-binding-wasm32-wasi@0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@rspack/resolver-binding-wasm32-wasi@0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': dependencies: - '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) transitivePeerDependencies: - '@emnapi/core' - '@emnapi/runtime' @@ -13808,7 +13546,7 @@ snapshots: '@rspack/resolver-binding-win32-x64-msvc@0.2.8': optional: true - '@rspack/resolver@0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1)': + '@rspack/resolver@0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2)': optionalDependencies: '@rspack/resolver-binding-darwin-arm64': 0.2.8 '@rspack/resolver-binding-darwin-x64': 0.2.8 @@ -13816,7 +13554,7 @@ snapshots: '@rspack/resolver-binding-linux-arm64-musl': 0.2.8 '@rspack/resolver-binding-linux-x64-gnu': 0.2.8 '@rspack/resolver-binding-linux-x64-musl': 0.2.8 - '@rspack/resolver-binding-wasm32-wasi': 0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.1) + '@rspack/resolver-binding-wasm32-wasi': 0.2.8(@emnapi/core@1.11.1)(@emnapi/runtime@1.11.2) '@rspack/resolver-binding-win32-arm64-msvc': 0.2.8 '@rspack/resolver-binding-win32-ia32-msvc': 0.2.8 '@rspack/resolver-binding-win32-x64-msvc': 0.2.8 @@ -13824,17 +13562,19 @@ snapshots: - '@emnapi/core' - '@emnapi/runtime' - '@rstest/core@0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0))': + '@rstest/core@0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0))': dependencies: - '@rsbuild/core': 1.7.2 + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) '@types/chai': 5.2.3 - tinypool: 1.1.1 optionalDependencies: jsdom: 27.4.0(@noble/hashes@2.2.0) + transitivePeerDependencies: + - '@module-federation/runtime-tools' + - core-js - '@rstest/coverage-istanbul@0.2.0(@rstest/core@0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0)))': + '@rstest/coverage-istanbul@0.11.0(@rstest/core@0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0)))': dependencies: - '@rstest/core': 0.8.1(jsdom@27.4.0(@noble/hashes@2.2.0)) + '@rstest/core': 0.11.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0)(jsdom@27.4.0(@noble/hashes@2.2.0)) istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-lib-source-maps: 5.0.6 @@ -14306,14 +14046,14 @@ snapshots: postcss: 8.5.15 tailwindcss: 4.3.1 - '@tailwindcss/webpack@4.3.2(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': + '@tailwindcss/webpack@4.3.2(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(webpack@5.108.1(lightningcss@1.32.0))': dependencies: '@alloc/quick-lru': 5.2.0 '@tailwindcss/node': 4.3.2 '@tailwindcss/oxide': 4.3.2 tailwindcss: 4.3.2 optionalDependencies: - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) webpack: 5.108.1(lightningcss@1.32.0) '@tanstack/devtools-client@0.0.5': @@ -14349,7 +14089,7 @@ snapshots: transitivePeerDependencies: - csstype - '@tanstack/devtools-vite@0.4.1(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))': + '@tanstack/devtools-vite@0.4.1(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))': dependencies: '@babel/core': 7.29.0 '@babel/generator': 7.29.7 @@ -14361,7 +14101,7 @@ snapshots: chalk: 5.6.2 launch-editor: 2.14.1 picomatch: 4.0.4 - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) transitivePeerDependencies: - bufferutil - supports-color @@ -14562,6 +14302,10 @@ snapshots: dependencies: undici-types: 7.16.0 + '@types/node@25.9.5': + dependencies: + undici-types: 7.24.6 + '@types/pegjs@0.10.6': {} '@types/pg-pool@2.0.7': @@ -14795,7 +14539,7 @@ snapshots: '@unrs/resolver-binding-win32-x64-msvc@1.12.2': optional: true - '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0))': + '@vitejs/plugin-react@5.1.2(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0))': dependencies: '@babel/core': 7.29.0 '@babel/plugin-transform-react-jsx-self': 7.29.7(@babel/core@7.29.0) @@ -14803,7 +14547,7 @@ snapshots: '@rolldown/pluginutils': 1.0.0-beta.53 '@types/babel__core': 7.20.5 react-refresh: 0.18.0 - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) transitivePeerDependencies: - supports-color @@ -15250,6 +14994,8 @@ snapshots: baseline-browser-mapping@2.10.40: {} + baseline-browser-mapping@2.10.42: {} + basic-auth@2.0.1: dependencies: safe-buffer: 5.1.2 @@ -15372,6 +15118,14 @@ snapshots: node-releases: 2.0.50 update-browserslist-db: 1.2.3(browserslist@4.28.4) + browserslist@4.28.5: + dependencies: + baseline-browser-mapping: 2.10.42 + caniuse-lite: 1.0.30001803 + electron-to-chromium: 1.5.389 + node-releases: 2.0.50 + update-browserslist-db: 1.2.3(browserslist@4.28.5) + buffer-from@1.1.2: {} buffer@5.7.1: @@ -15417,6 +15171,8 @@ snapshots: caniuse-lite@1.0.30001799: {} + caniuse-lite@1.0.30001803: {} + chain-function@1.0.1: {} chalk-template@0.4.0: @@ -15587,7 +15343,8 @@ snapshots: dependencies: is-what: 4.1.16 - core-js@3.47.0: {} + core-js@3.47.0: + optional: true core-util-is@1.0.3: {} @@ -15889,6 +15646,8 @@ snapshots: electron-to-chromium@1.5.380: {} + electron-to-chromium@1.5.389: {} + emoji-regex@8.0.0: {} emoji-regex@9.2.2: {} @@ -15931,7 +15690,7 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.3 - enhanced-resolve@5.24.1: + enhanced-resolve@5.24.2: dependencies: graceful-fs: 4.2.11 tapable: 2.3.3 @@ -16053,6 +15812,8 @@ snapshots: es-module-lexer@2.1.0: {} + es-module-lexer@2.3.0: {} + es-object-atoms@1.1.2: dependencies: es-errors: 1.3.0 @@ -17107,7 +16868,7 @@ snapshots: jest-worker@27.5.1: dependencies: - '@types/node': 25.0.10 + '@types/node': 25.9.5 merge-stream: 2.0.0 supports-color: 8.1.1 @@ -17234,11 +16995,11 @@ snapshots: leaflet@1.9.4: {} - less-loader@12.3.3(@rspack/core@2.1.0(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(less@4.6.7)(webpack@5.108.1(lightningcss@1.32.0)): + less-loader@12.3.3(@rspack/core@2.1.3(@module-federation/runtime-tools@2.5.1)(@swc/helpers@0.5.23))(less@4.6.7)(webpack@5.108.1(lightningcss@1.32.0)): dependencies: less: 4.6.7 optionalDependencies: - '@rspack/core': 2.1.0(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) + '@rspack/core': 2.1.3(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(@swc/helpers@0.5.23) webpack: 5.108.1(lightningcss@1.32.0) less@4.6.7: @@ -17521,7 +17282,7 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 - terser: 5.48.0 + terser: 5.49.0 webpack: 5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16) optionalDependencies: esbuild: 0.27.2 @@ -17534,7 +17295,7 @@ snapshots: '@jridgewell/trace-mapping': 0.3.31 jest-worker: 27.5.1 schema-utils: 4.3.3 - terser: 5.48.0 + terser: 5.49.0 webpack: 5.108.1(lightningcss@1.32.0) optionalDependencies: lightningcss: 1.32.0 @@ -18214,7 +17975,7 @@ snapshots: optionalDependencies: '@types/react': 19.2.10 - react-router-devtools@6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)): + react-router-devtools@6.2.1(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react-router@7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7))(react@19.2.7)(solid-js@1.9.13)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)): dependencies: '@babel/core': 7.29.0 '@babel/generator': 7.29.7 @@ -18224,7 +17985,7 @@ snapshots: '@radix-ui/react-accordion': 1.2.14(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(react-dom@19.2.7(react@19.2.7))(react@19.2.7) '@tanstack/devtools-client': 0.0.5 '@tanstack/devtools-event-client': 0.4.4 - '@tanstack/devtools-vite': 0.4.1(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)) + '@tanstack/devtools-vite': 0.4.1(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)) '@tanstack/react-devtools': 0.9.13(@types/react-dom@19.2.3(@types/react@19.2.10))(@types/react@19.2.10)(csstype@3.2.3)(react-dom@19.2.7(react@19.2.7))(react@19.2.7)(solid-js@1.9.13) '@types/react': 19.2.10 '@types/react-dom': 19.2.3(@types/react@19.2.10) @@ -18238,7 +17999,7 @@ snapshots: react-hotkeys-hook: 5.3.3(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-router: 7.18.0(react-dom@19.2.7(react@19.2.7))(react@19.2.7) react-tooltip: 5.30.1(react-dom@19.2.7(react@19.2.7))(react@19.2.7) - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) optionalDependencies: '@biomejs/cli-darwin-arm64': 2.5.1 '@rollup/rollup-darwin-arm64': 4.62.2 @@ -18508,10 +18269,10 @@ snapshots: transitivePeerDependencies: - supports-color - rsbuild-plugin-dts@0.22.1(@rsbuild/core@2.0.15(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(typescript@5.9.3): + rsbuild-plugin-dts@0.23.2(@rsbuild/core@2.1.5(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0))(typescript@5.9.3): dependencies: '@ast-grep/napi': 0.37.0 - '@rsbuild/core': 2.0.15(@module-federation/runtime-tools@2.5.1)(core-js@3.47.0) + '@rsbuild/core': 2.1.5(@module-federation/runtime-tools@2.5.1(node-fetch@2.7.0(encoding@0.1.13)))(core-js@3.47.0) optionalDependencies: typescript: 5.9.3 @@ -18714,11 +18475,11 @@ snapshots: transitivePeerDependencies: - supports-color - seroval-plugins@1.5.4(seroval@1.5.4): + seroval-plugins@1.5.5(seroval@1.5.5): dependencies: - seroval: 1.5.4 + seroval: 1.5.5 - seroval@1.5.4: {} + seroval@1.5.5: {} serve-handler@6.1.7: dependencies: @@ -18927,8 +18688,8 @@ snapshots: solid-js@1.9.13: dependencies: csstype: 3.2.3 - seroval: 1.5.4 - seroval-plugins: 1.5.4(seroval@1.5.4) + seroval: 1.5.5 + seroval-plugins: 1.5.5(seroval@1.5.5) sonner@2.0.7(react-dom@19.2.7(react@19.2.7))(react@19.2.7): dependencies: @@ -19175,7 +18936,7 @@ snapshots: term-size@2.2.1: {} - terser@5.48.0: + terser@5.49.0: dependencies: '@jridgewell/source-map': 0.3.11 acorn: 8.17.0 @@ -19189,8 +18950,6 @@ snapshots: fdir: 6.5.0(picomatch@4.0.4) picomatch: 4.0.4 - tinypool@1.1.1: {} - tldts-core@7.4.5: {} tldts@7.4.5: @@ -19332,6 +19091,8 @@ snapshots: undici-types@7.16.0: {} + undici-types@7.24.6: {} + undici@7.24.7: {} undici@7.28.0: {} @@ -19392,6 +19153,12 @@ snapshots: escalade: 3.2.0 picocolors: 1.1.1 + update-browserslist-db@1.2.3(browserslist@4.28.5): + dependencies: + browserslist: 4.28.5 + escalade: 3.2.0 + picocolors: 1.1.1 + update-check@1.5.4: dependencies: registry-auth-token: 3.3.2 @@ -19446,7 +19213,7 @@ snapshots: vary@1.1.2: {} - vite-env-only@3.0.3(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)): + vite-env-only@3.0.3(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)): dependencies: '@babel/core': 7.29.0 '@babel/generator': 7.29.7 @@ -19455,17 +19222,38 @@ snapshots: '@babel/types': 7.29.7 babel-dead-code-elimination: 1.0.12 micromatch: 4.0.8 - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) transitivePeerDependencies: - supports-color - vite-node@3.2.4(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0): + vite-node@3.2.4(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0): + dependencies: + cac: 6.7.14 + debug: 4.4.3 + es-module-lexer: 1.7.0 + pathe: 2.0.3 + vite: 7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) + transitivePeerDependencies: + - '@types/node' + - jiti + - less + - lightningcss + - sass + - sass-embedded + - stylus + - sugarss + - supports-color + - terser + - tsx + - yaml + + vite-node@3.2.4(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) transitivePeerDependencies: - '@types/node' - jiti @@ -19480,13 +19268,13 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0): + vite-node@3.2.4(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) transitivePeerDependencies: - '@types/node' - jiti @@ -19501,17 +19289,17 @@ snapshots: - tsx - yaml - vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0)): + vite-tsconfig-paths@6.1.1(typescript@5.9.3)(vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0)): dependencies: debug: 4.4.3 globrex: 0.1.2 tsconfck: 3.1.6(typescript@5.9.3) - vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0) + vite: 7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0) transitivePeerDependencies: - supports-color - typescript - vite@7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0): + vite@7.3.1(@types/node@22.15.31)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.4) @@ -19527,10 +19315,10 @@ snapshots: lightningcss: 1.32.0 sass: 1.100.0 sass-embedded: 1.100.0 - terser: 5.48.0 + terser: 5.49.0 tsx: 4.21.0 - vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.48.0)(tsx@4.21.0): + vite@7.3.1(@types/node@25.0.10)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0): dependencies: esbuild: 0.27.2 fdir: 6.5.0(picomatch@4.0.4) @@ -19546,7 +19334,26 @@ snapshots: lightningcss: 1.32.0 sass: 1.100.0 sass-embedded: 1.100.0 - terser: 5.48.0 + terser: 5.49.0 + tsx: 4.21.0 + + vite@7.3.1(@types/node@25.9.5)(jiti@2.7.0)(less@4.6.7)(lightningcss@1.32.0)(sass-embedded@1.100.0)(sass@1.100.0)(terser@5.49.0)(tsx@4.21.0): + dependencies: + esbuild: 0.27.2 + fdir: 6.5.0(picomatch@4.0.4) + picomatch: 4.0.4 + postcss: 8.5.16 + rollup: 4.62.2 + tinyglobby: 0.2.17 + optionalDependencies: + '@types/node': 25.9.5 + fsevents: 2.3.3 + jiti: 2.7.0 + less: 4.6.7 + lightningcss: 1.32.0 + sass: 1.100.0 + sass-embedded: 1.100.0 + terser: 5.49.0 tsx: 4.21.0 w3c-xmlserializer@5.0.0: @@ -19571,6 +19378,8 @@ snapshots: webpack-sources@3.5.0: {} + webpack-sources@3.5.1: {} + webpack-virtual-modules@0.5.0: {} webpack@5.108.1(esbuild@0.27.2)(lightningcss@1.32.0)(postcss@8.5.16): @@ -19582,10 +19391,10 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.17.0 acorn-import-phases: 1.0.4(acorn@8.17.0) - browserslist: 4.28.4 + browserslist: 4.28.5 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.24.1 - es-module-lexer: 2.1.0 + enhanced-resolve: 5.24.2 + es-module-lexer: 2.3.0 eslint-scope: 5.1.1 events: 3.3.0 graceful-fs: 4.2.11 @@ -19596,7 +19405,7 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.3 watchpack: 2.5.2 - webpack-sources: 3.5.0 + webpack-sources: 3.5.1 transitivePeerDependencies: - '@minify-html/node' - '@swc/core' @@ -19621,10 +19430,10 @@ snapshots: '@webassemblyjs/wasm-parser': 1.14.1 acorn: 8.17.0 acorn-import-phases: 1.0.4(acorn@8.17.0) - browserslist: 4.28.4 + browserslist: 4.28.5 chrome-trace-event: 1.0.4 - enhanced-resolve: 5.24.1 - es-module-lexer: 2.1.0 + enhanced-resolve: 5.24.2 + es-module-lexer: 2.3.0 eslint-scope: 5.1.1 events: 3.3.0 graceful-fs: 4.2.11 @@ -19635,7 +19444,7 @@ snapshots: schema-utils: 4.3.3 tapable: 2.3.3 watchpack: 2.5.2 - webpack-sources: 3.5.0 + webpack-sources: 3.5.1 transitivePeerDependencies: - '@minify-html/node' - '@swc/core' diff --git a/rslib.config.ts b/rslib.config.ts index 566bf25c..80e3488e 100644 --- a/rslib.config.ts +++ b/rslib.config.ts @@ -11,8 +11,8 @@ const config = defineConfig({ source: { entry: { index: './src/index.ts', - 'parallel-route-transform-worker': - './src/parallel-route-transform-worker.ts', + 'route-module-transform-loader': + './src/route-module-transform-loader.ts', 'templates/entry.server': './src/templates/entry.server.tsx', 'templates/entry.client': './src/templates/entry.client.tsx', }, diff --git a/scripts/benchmark/results.mts b/scripts/benchmark/results.mts index 67c678be..641204b1 100644 --- a/scripts/benchmark/results.mts +++ b/scripts/benchmark/results.mts @@ -174,7 +174,7 @@ const formatParallelRouteTransform = parallelRouteTransform => { if (parallelRouteTransform === true) { return 'true'; } - return `workers=${parallelRouteTransform}`; + return `maxWorkers=${parallelRouteTransform}`; }; const appendDevRequestSummary = (lines, benchmark, key, title) => { diff --git a/src/build-output-transforms.ts b/src/build-output-transforms.ts index c06bae2e..7038557e 100644 --- a/src/build-output-transforms.ts +++ b/src/build-output-transforms.ts @@ -36,6 +36,7 @@ type RegisterBuildOutputTransformsOptions = { routeChunkConfig: RouteChunkConfig; isBuild: boolean; splitRouteModules: boolean; + useApiRouteModuleTransforms: boolean; ssr: boolean; isSpaMode: boolean; rootRoutePath: string; @@ -58,6 +59,7 @@ export const registerBuildOutputTransforms = ({ routeChunkConfig, isBuild, splitRouteModules, + useApiRouteModuleTransforms, ssr, isSpaMode, rootRoutePath, @@ -252,22 +254,24 @@ export const registerBuildOutputTransforms = ({ ) ); - api.transform( - { - resourceQuery: /\?react-router-route/, - order: 'post', - }, - transformRouteModule - ); + if (useApiRouteModuleTransforms) { + api.transform( + { + resourceQuery: /\?react-router-route/, + order: 'post', + }, + transformRouteModule + ); - api.transform( - { - test: path => routeByFilePath.has(path), - resourceQuery: { - not: /__react-router-build-client-route|react-router-route|route-chunk=/, + api.transform( + { + test: path => routeByFilePath.has(path), + resourceQuery: { + not: /__react-router-build-client-route|react-router-route|route-chunk=/, + }, + order: 'post', }, - order: 'post', - }, - transformRouteModule - ); + transformRouteModule + ); + } }; diff --git a/src/dev-background-resources.ts b/src/dev-background-resources.ts index 64a979a3..70d21d98 100644 --- a/src/dev-background-resources.ts +++ b/src/dev-background-resources.ts @@ -214,8 +214,6 @@ export const registerReactRouterDevBackgroundResources = ({ lazyCompilationPrewarmController?.schedule(); }); - // Spawn transform workers now so thread startup overlaps Rsbuild's own - // compiler creation instead of delaying the first route transform. routeTransformExecutor.prewarm(); } diff --git a/src/index.ts b/src/index.ts index 7238c38e..b34f26b8 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,5 @@ import { existsSync, readFileSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; import fsExtra from 'fs-extra'; import type { Config } from './react-router-config.js'; import type { RouteConfigEntry } from '@react-router/dev/routes'; @@ -55,6 +56,7 @@ import { createRouteTransformExecutor, shouldParallelizeRouteTransforms, } from './parallel-route-transforms.js'; +import type { RouteModuleTransformLoaderOptions } from './route-module-transform-loader.js'; import { getRouteRestartMarkerPath, mergeWatchFiles } from './route-watch.js'; import { validateRouteConfig } from './route-config.js'; import { @@ -137,6 +139,47 @@ const cssUrlAssetExtensions = /\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/; const urlAssetResourceQuery = /^(?=.*(?:\?|&)url(?:&|$))(?!.*(?:\?|&)(?:raw|inline)(?:&|$))/; +const routeModuleTransformLoaderPath = fileURLToPath( + new URL('./route-module-transform-loader.js', import.meta.url) +); +const useApiRouteModuleTransforms = + existsSync( + fileURLToPath( + new URL('./route-module-transform-loader.ts', import.meta.url) + ) + ) || process.env.RSTEST === 'true'; + +const getRouteModuleTransformParallel = ( + parallelRouteTransform: PluginOptions['parallelRouteTransform'] +): Rspack.RuleSetLoaderWithOptions['parallel'] => { + if (parallelRouteTransform === true) { + return true; + } + if (typeof parallelRouteTransform === 'number') { + if ( + !Number.isInteger(parallelRouteTransform) || + parallelRouteTransform < 1 + ) { + throw new Error( + '[react-router] parallelRouteTransform must be true, false, or a positive integer.' + ); + } + return { maxWorkers: parallelRouteTransform }; + } + return undefined; +}; + +const createRouteModuleTransformUse = ( + options: RouteModuleTransformLoaderOptions, + parallelRouteTransform: PluginOptions['parallelRouteTransform'] +): Rspack.RuleSetLoaderWithOptions => { + const parallel = getRouteModuleTransformParallel(parallelRouteTransform); + return { + loader: routeModuleTransformLoaderPath, + options, + ...(parallel ? { parallel } : {}), + }; +}; export const pluginReactRouter = ( options: PluginOptions = {} @@ -420,13 +463,11 @@ export const pluginReactRouter = ( rootRouteFile, }; const routeChunkCache: RouteChunkCache = new Map(); + const parallelRouteTransform = + pluginOptions.parallelRouteTransform ?? + shouldParallelizeRouteTransforms(routeCount); const routeTransformExecutor = createRouteTransformExecutor({ - parallelRouteTransform: - pluginOptions.parallelRouteTransform ?? - shouldParallelizeRouteTransforms(routeCount), routeChunkCache, - splitRouteModules: Boolean(splitRouteModules), - isBuild, }); const routeChunkOptions = { splitRouteModules, @@ -748,7 +789,6 @@ export const pluginReactRouter = ( routeCount >= 256 && (config.performance?.printFileSize === undefined || config.performance.printFileSize === true); - return mergeRsbuildConfig(config, { ...(shouldCompactFileSizeReport ? { @@ -765,7 +805,6 @@ export const pluginReactRouter = ( assetPrefix: config.output?.assetPrefix || '/', }, dev: { - writeToDisk: true, ...lazyCompilation, watchFiles: mergeWatchFiles(config.dev?.watchFiles, routeWatchFiles), }, @@ -909,6 +948,36 @@ export const pluginReactRouter = ( return mergeEnvironmentConfig(config, { tools: { rspack: rspackConfig => { + if (!useApiRouteModuleTransforms) { + const routeModuleTransformUse = createRouteModuleTransformUse( + { + environmentName: name, + ssr, + isBuild, + isSpaMode, + rootRoutePath, + }, + parallelRouteTransform + ); + rspackConfig.module ??= {}; + rspackConfig.module.rules ??= []; + rspackConfig.module.rules.push( + { + resourceQuery: /\?react-router-route/, + enforce: 'post', + use: [routeModuleTransformUse], + }, + { + test: path => routeByFilePath.has(path), + resourceQuery: { + not: /__react-router-build-client-route|react-router-route|route-chunk=/, + }, + enforce: 'post', + use: [routeModuleTransformUse], + } + ); + } + if (pluginOptions.federation) { ensureFederationAsyncStartup(rspackConfig); } @@ -982,6 +1051,7 @@ export const pluginReactRouter = ( routeChunkConfig, isBuild, splitRouteModules: Boolean(splitRouteModules), + useApiRouteModuleTransforms, ssr, isSpaMode, rootRoutePath, diff --git a/src/parallel-route-transform-protocol.ts b/src/parallel-route-transform-protocol.ts deleted file mode 100644 index 24929229..00000000 --- a/src/parallel-route-transform-protocol.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { - RouteTransformResult, - RouteTransformTask, -} from './route-transform-tasks.js'; - -type WithoutRequiredSource = Task extends RouteTransformTask - ? Omit & { code?: string } - : never; - -export type CachedRouteTransformTask = - WithoutRequiredSource; - -export type WorkerRequest = { - id: number; - task: RouteTransformTask | CachedRouteTransformTask; - sourceCacheKey?: string; -}; - -export type WorkerErrorPayload = { - name?: string; - message: string; - stack?: string; -}; - -export type WorkerResponse = - | { - id: number; - ok: true; - result: RouteTransformResult; - } - | { - id: number; - ok: false; - error: WorkerErrorPayload; - }; diff --git a/src/parallel-route-transform-worker.ts b/src/parallel-route-transform-worker.ts deleted file mode 100644 index 36e85e2f..00000000 --- a/src/parallel-route-transform-worker.ts +++ /dev/null @@ -1,82 +0,0 @@ -import { parentPort } from 'node:worker_threads'; -import { setBoundedCacheEntry } from './bounded-cache.js'; -import { - executeRouteTransformTask, - type RouteTransformTask, -} from './route-transform-tasks.js'; -import type { - WorkerErrorPayload, - WorkerRequest, - WorkerResponse, -} from './parallel-route-transform-protocol.js'; - -const serializeError = (error: unknown): WorkerErrorPayload => { - if (error instanceof Error) { - return { - name: error.name, - message: error.message, - stack: error.stack, - }; - } - return { - message: String(error), - }; -}; - -if (!parentPort) { - throw new Error('parallel route transform worker requires parentPort'); -} - -const MAX_SOURCE_CACHE_ENTRIES = 2048; -const sourceCache = new Map(); - -const hydrateTaskSource = ({ - task, - sourceCacheKey, -}: Pick): RouteTransformTask => { - if (!sourceCacheKey) { - return task as RouteTransformTask; - } - - if (typeof task.code === 'string') { - setBoundedCacheEntry( - sourceCache, - sourceCacheKey, - task.code, - MAX_SOURCE_CACHE_ENTRIES - ); - return task as RouteTransformTask; - } - - const code = sourceCache.get(sourceCacheKey); - if (code === undefined) { - throw new Error( - `Missing cached route transform source for ${sourceCacheKey}.` - ); - } - return { - ...task, - code, - } as RouteTransformTask; -}; - -parentPort.on( - 'message', - async ({ id, task, sourceCacheKey }: WorkerRequest) => { - try { - const hydratedTask = hydrateTaskSource({ task, sourceCacheKey }); - const result = await executeRouteTransformTask(hydratedTask); - parentPort?.postMessage({ - id, - ok: true, - result, - } satisfies WorkerResponse); - } catch (error) { - parentPort?.postMessage({ - id, - ok: false, - error: serializeError(error), - } satisfies WorkerResponse); - } - } -); diff --git a/src/parallel-route-transforms.ts b/src/parallel-route-transforms.ts index 06adae3e..1ef47e22 100644 --- a/src/parallel-route-transforms.ts +++ b/src/parallel-route-transforms.ts @@ -1,458 +1,27 @@ -import { Worker } from 'node:worker_threads'; -import { setBoundedCacheEntry } from './bounded-cache.js'; -import { getAvailableCpuCount, getDefaultConcurrency } from './concurrency.js'; -import { normalizeEffectError } from './effect-runtime.js'; import { executeRouteTransformTask, type RouteTransformResult, type RouteTransformTask, type RouteTransformTaskOptions, } from './route-transform-tasks.js'; -import type { PluginOptions } from './types.js'; -import type { - WorkerErrorPayload, - WorkerRequest, - WorkerResponse, -} from './parallel-route-transform-protocol.js'; -export type ParallelRouteTransformConfig = - NonNullable extends infer Config - ? Exclude - : never; - -export type RouteTransformExecutorOptions = RouteTransformTaskOptions & { - parallelRouteTransform?: PluginOptions['parallelRouteTransform']; - splitRouteModules?: boolean; - isBuild?: boolean; -}; - -export type RouteTransformExecutor = { - run: (task: RouteTransformTask) => Promise; - prewarm: () => void; - close: () => Promise; -}; - -type PendingTask = { - resolve: (result: RouteTransformResult) => void; - reject: (error: Error) => void; -}; - -type RouteTransformWorker = { - on(event: 'message', handler: (response: WorkerResponse) => void): unknown; - on(event: 'error', handler: (error: Error) => void): unknown; - on(event: 'exit', handler: (code: number) => void): unknown; - postMessage(message: WorkerRequest): void; - terminate(): Promise | number; -}; - -type RouteTransformWorkerFactory = () => RouteTransformWorker; - -type WorkerState = { - worker: RouteTransformWorker; - pending: Map; - sourceCache: Map; -}; - -class WorkerStartupError extends Error { - constructor(message: string) { - super(message); - this.name = 'WorkerStartupError'; - } -} - -const MAX_WORKER_SOURCE_CACHE_ENTRIES = 2048; -const MAX_ROUTE_SOURCE_WORKER_ENTRIES = 4096; const AUTO_PARALLEL_ROUTE_THRESHOLD = 256; -const DEFAULT_WORKER_COUNT_LIMIT = 2; -// Benchmarked on a 4-core cpuset: in dev (large-355 fixture) a single worker -// recovered no wall time while worker startup and IPC cost ~0.5s of -// dev-server ready (9.09s -> 8.57s median when disabled), so small machines -// run dev transforms inline. Production builds are different: at 1024 routes -// the transform volume is large enough that two workers beat inline by ~8% -// (synthetic-1024-ssr-esm build, 4.46s inline vs 4.09s with workers), so -// builds keep the default worker count even on small machines. -const SMALL_MACHINE_CPU_COUNT = 4; - -export const getDefaultWorkerCount = ( - cpuCount?: number, - { isBuild = false }: { isBuild?: boolean } = {} -): number => { - const resolvedCpuCount = cpuCount ?? getAvailableCpuCount(); - if (!isBuild && resolvedCpuCount <= SMALL_MACHINE_CPU_COUNT) { - return 0; - } - return Math.min( - getDefaultConcurrency(resolvedCpuCount), - DEFAULT_WORKER_COUNT_LIMIT - ); -}; export const shouldParallelizeRouteTransforms = (routeCount: number): boolean => routeCount >= AUTO_PARALLEL_ROUTE_THRESHOLD; -const getConfiguredWorkerCount = ( - parallelRouteTransform: ParallelRouteTransformConfig, - isBuild: boolean -): number => { - if (parallelRouteTransform === true) { - return getDefaultWorkerCount(undefined, { isBuild }); - } - - if (!Number.isInteger(parallelRouteTransform) || parallelRouteTransform < 1) { - throw new Error( - '[react-router] parallelRouteTransform must be true, false, or a positive integer.' - ); - } - return parallelRouteTransform; -}; - -const hashString = (value: string): number => { - let hash = 0; - for (let index = 0; index < value.length; index += 1) { - hash = (hash * 31 + value.charCodeAt(index)) >>> 0; - } - return hash; -}; +export type RouteTransformExecutorOptions = RouteTransformTaskOptions; -const deserializeWorkerError = (error: WorkerErrorPayload): Error => { - const result = new Error(error.message); - result.name = error.name ?? 'Error'; - if (error.stack) { - result.stack = error.stack; - } - return result; -}; - -const createWorkerUrl = (): URL => - new URL('./parallel-route-transform-worker.js', import.meta.url); - -const createDefaultWorker = (): RouteTransformWorker => - new Worker(createWorkerUrl()); - -const isWorkerStartupError = (error: unknown): error is WorkerStartupError => - error instanceof WorkerStartupError; - -const createWorkerStartupError = (error: unknown): WorkerStartupError => { - const normalized = normalizeEffectError(error); - const startupError = new WorkerStartupError(normalized.message); - startupError.stack = normalized.stack; - return startupError; -}; - -const rejectPendingTasks = (state: WorkerState, error: Error): void => { - for (const pending of state.pending.values()) { - pending.reject(error); - } - state.pending.clear(); +export type RouteTransformExecutor = { + run: (task: RouteTransformTask) => Promise; + prewarm: () => void; + close: () => Promise; }; -const createInlineRouteTransformExecutor = ( - options: RouteTransformTaskOptions +export const createRouteTransformExecutor = ( + options: RouteTransformExecutorOptions = {} ): RouteTransformExecutor => ({ run: task => executeRouteTransformTask(task, options), prewarm: () => {}, close: async () => {}, }); - -class ParallelRouteTransformExecutor implements RouteTransformExecutor { - #closed = false; - #closePromise: Promise | undefined; - #workersDisabled = false; - #nextId = 1; - #nextRouteSourceWorkerIndex = 0; - #routeSourceWorkers = new Map(); - #workers: Array | undefined; - #prewarmScheduled = false; - - constructor( - private readonly workerCount: number, - private readonly options: RouteTransformTaskOptions, - private readonly balanceRouteModuleTransforms: boolean, - private readonly createWorker: RouteTransformWorkerFactory - ) {} - - async run(task: RouteTransformTask): Promise { - if (this.#closed) { - return executeRouteTransformTask(task, this.options); - } - if (task.kind === 'clientOnlyStub' && task.resolveExportAllModule) { - return executeRouteTransformTask(task, this.options); - } - - try { - return await this.#runInWorker(task); - } catch (error) { - if (isWorkerStartupError(error)) { - return executeRouteTransformTask(task, this.options); - } - throw error; - } - } - - prewarm(): void { - if (this.#prewarmScheduled || this.#closed || this.#workersDisabled) { - return; - } - this.#prewarmScheduled = true; - void this.#prewarmWorkers(); - } - - async #prewarmWorkers(): Promise { - try { - for (let index = 0; index < this.workerCount; index += 1) { - if (this.#closed || this.#workersDisabled) { - return; - } - try { - this.#getWorker(index); - } catch (error) { - this.#disableWorkers(createWorkerStartupError(error)); - return; - } - } - } finally { - this.#prewarmScheduled = false; - } - } - - close(): Promise { - if (this.#closePromise) { - return this.#closePromise; - } - this.#closed = true; - const workers = (this.#workers ?? []).filter( - (state): state is WorkerState => Boolean(state) - ); - this.#workers = []; - this.#closePromise = Promise.all( - workers.map(async state => { - rejectPendingTasks(state, new Error('Route transform worker closed.')); - await state.worker.terminate(); - }) - ).then(() => undefined); - return this.#closePromise; - } - - #disableWorkers(error: WorkerStartupError): void { - if (this.#workersDisabled || this.#closed) { - return; - } - this.#workersDisabled = true; - const workers = (this.#workers ?? []).filter( - (state): state is WorkerState => Boolean(state) - ); - this.#workers = []; - for (const state of workers) { - rejectPendingTasks(state, error); - void state.worker.terminate(); - } - } - - #createWorkerState(): WorkerState { - const worker = this.createWorker(); - const state: WorkerState = { - worker, - pending: new Map(), - sourceCache: new Map(), - }; - - worker.on('message', (response: WorkerResponse) => { - const pending = state.pending.get(response.id); - if (!pending) { - return; - } - state.pending.delete(response.id); - if (response.ok) { - pending.resolve(response.result); - } else { - pending.reject(deserializeWorkerError(response.error)); - } - }); - - worker.on('error', (error: Error) => { - this.#disableWorkers(createWorkerStartupError(error)); - }); - - worker.on('exit', code => { - if (this.#closed || this.#workersDisabled) { - return; - } - const startupError = new WorkerStartupError( - `Route transform worker exited with code ${code}.` - ); - this.#disableWorkers(startupError); - }); - - return state; - } - - #getWorker(index: number): WorkerState | undefined { - if (this.#closed || this.#workersDisabled) { - return undefined; - } - this.#workers ??= new Array(this.workerCount); - const existingWorker = this.#workers[index]; - if (existingWorker) { - return existingWorker; - } - - const worker = this.#createWorkerState(); - this.#workers[index] = worker; - return worker; - } - - #runInWorker(task: RouteTransformTask): Promise { - const workerIndex = this.#getWorkerIndex(task, this.workerCount); - const state = this.#getWorker(workerIndex); - if (!state) { - return executeRouteTransformTask(task, this.options); - } - - const id = this.#nextId++; - const sourceCacheKey = task.resourcePath; - const requestTask = this.#createWorkerRequestTask( - state, - task, - sourceCacheKey - ); - return new Promise((resolve, reject) => { - state.pending.set(id, { resolve, reject }); - try { - state.worker.postMessage({ - id, - task: requestTask, - sourceCacheKey, - } satisfies WorkerRequest); - } catch (error) { - state.pending.delete(id); - // The worker may not have received the source update. Force the next - // request for this module to send its full source again. - state.sourceCache.delete(sourceCacheKey); - reject(normalizeEffectError(error)); - } - }); - } - - #createWorkerRequestTask( - state: WorkerState, - task: RouteTransformTask, - sourceCacheKey: string - ): WorkerRequest['task'] { - const cachedSource = state.sourceCache.get(sourceCacheKey); - if (cachedSource === task.code) { - const { code: _code, ...cachedTask } = task; - return cachedTask; - } - - setBoundedCacheEntry( - state.sourceCache, - sourceCacheKey, - task.code, - MAX_WORKER_SOURCE_CACHE_ENTRIES - ); - return task; - } - - #getWorkerIndex(task: RouteTransformTask, workerCount: number): number { - const safeWorkerCount = Math.max(1, workerCount); - if ( - this.balanceRouteModuleTransforms && - (task.kind === 'routeClientEntry' || - task.kind === 'routeChunk' || - task.kind === 'splitRouteExports') - ) { - return this.#getRouteSourceWorkerIndex( - task.resourcePath, - safeWorkerCount - ); - } - if ( - this.balanceRouteModuleTransforms && - task.kind === 'routeModule' && - !(task.environmentName === 'web' && !task.ssr && task.isSpaMode) - ) { - return this.#getRouteSourceWorkerIndex( - task.resourcePath, - safeWorkerCount - ); - } - return hashString(task.resourcePath) % safeWorkerCount; - } - - #getRouteSourceWorkerIndex( - resourcePath: string, - safeWorkerCount: number - ): number { - const existingWorkerIndex = this.#routeSourceWorkers.get(resourcePath); - if (existingWorkerIndex !== undefined) { - this.#routeSourceWorkers.delete(resourcePath); - this.#routeSourceWorkers.set(resourcePath, existingWorkerIndex); - return existingWorkerIndex % safeWorkerCount; - } - const workerIndex = this.#nextRouteSourceWorkerIndex % safeWorkerCount; - this.#nextRouteSourceWorkerIndex += 1; - setBoundedCacheEntry( - this.#routeSourceWorkers, - resourcePath, - workerIndex, - MAX_ROUTE_SOURCE_WORKER_ENTRIES - ); - return workerIndex; - } -} - -export const createRouteTransformExecutor = ({ - parallelRouteTransform, - routeChunkCache, - splitRouteModules, - isBuild, -}: RouteTransformExecutorOptions = {}): RouteTransformExecutor => { - return createRouteTransformExecutorWithWorkerFactory( - { - parallelRouteTransform, - routeChunkCache, - splitRouteModules, - isBuild, - }, - createDefaultWorker - ); -}; - -const createRouteTransformExecutorWithWorkerFactory = ( - { - parallelRouteTransform, - routeChunkCache, - splitRouteModules, - isBuild, - }: RouteTransformExecutorOptions = {}, - createWorker: RouteTransformWorkerFactory -): RouteTransformExecutor => { - const options = { routeChunkCache }; - if ( - parallelRouteTransform === undefined || - parallelRouteTransform === false - ) { - return createInlineRouteTransformExecutor(options); - } - - const workerCount = getConfiguredWorkerCount( - parallelRouteTransform, - Boolean(isBuild) - ); - if (workerCount < 1) { - return createInlineRouteTransformExecutor(options); - } - - return new ParallelRouteTransformExecutor( - workerCount, - options, - Boolean(splitRouteModules), - createWorker - ); -}; - -export const createRouteTransformExecutorForTesting = ( - options: RouteTransformExecutorOptions, - createWorker: RouteTransformWorkerFactory -): RouteTransformExecutor => - createRouteTransformExecutorWithWorkerFactory(options, createWorker); diff --git a/src/route-module-transform-loader.ts b/src/route-module-transform-loader.ts new file mode 100644 index 00000000..91385cf9 --- /dev/null +++ b/src/route-module-transform-loader.ts @@ -0,0 +1,46 @@ +import type { LoaderDefinition } from '@rspack/core'; +import { executeRouteTransformTask } from './route-transform-tasks.js'; + +export type RouteModuleTransformLoaderOptions = { + environmentName: string; + ssr: boolean; + isBuild: boolean; + isSpaMode: boolean; + rootRoutePath: string | null; +}; + +type LoaderContextWithSourceMap = ThisParameterType< + LoaderDefinition +> & { + sourceMap?: boolean; +}; + +const routeModuleTransformLoader: LoaderDefinition = + async function routeModuleTransformLoader( + this: LoaderContextWithSourceMap, + source + ) { + const callback = this.async(); + const options = this.getOptions(); + + try { + const result = await executeRouteTransformTask({ + kind: 'routeModule', + code: String(source), + resource: this.resource, + resourcePath: this.resourcePath, + environmentName: options.environmentName, + sourceMaps: Boolean(this.sourceMap), + ssr: options.ssr, + isBuild: options.isBuild, + isSpaMode: options.isSpaMode, + rootRoutePath: options.rootRoutePath, + }); + + callback(null, result.code, result.map ?? undefined); + } catch (error) { + callback(error instanceof Error ? error : new Error(String(error))); + } + }; + +export default routeModuleTransformLoader; diff --git a/src/types.ts b/src/types.ts index 8029eec0..83499b12 100644 --- a/src/types.ts +++ b/src/types.ts @@ -57,11 +57,10 @@ export type PluginOptions = { logPerformance?: boolean; /** - * Run route transforms in a worker-thread pool. - * Pass `true` to force the default worker count, a positive integer to set - * the worker count, or `false` to disable. - * @default Automatically enabled for 256+ resolved routes. The automatic - * pool uses available CPU cores minus 2. + * Run route module transforms with Rspack's parallel loader workers. + * Pass `true` to use Rspack's default worker count, a positive integer to set + * the maximum worker count, or `false` to disable. + * @default Automatically enabled for 256+ resolved routes. */ parallelRouteTransform?: boolean | number; diff --git a/tests/build-output-transforms.test.ts b/tests/build-output-transforms.test.ts index b080e5b4..2cc23aca 100644 --- a/tests/build-output-transforms.test.ts +++ b/tests/build-output-transforms.test.ts @@ -23,7 +23,8 @@ const createTransformHarness = () => { }; const createBaseOptions = ( - transforms: ReturnType + transforms: ReturnType, + useApiRouteModuleTransforms = false ) => { const appDirectory = resolve('/project/app'); const routePath = resolve(appDirectory, 'routes/page.tsx'); @@ -57,6 +58,7 @@ const createBaseOptions = ( }, isBuild: true, splitRouteModules: true, + useApiRouteModuleTransforms, ssr: true, isSpaMode: false, rootRoutePath: resolve(appDirectory, 'root.tsx'), @@ -81,12 +83,33 @@ const createTransformArgs = ( }) as never; describe('build output transforms', () => { - it('registers post-order route-module transforms for explicit and queryless route modules', async () => { + it('does not register route-module transforms through api.transform', () => { const harness = createTransformHarness(); const options = createBaseOptions(harness); registerBuildOutputTransforms(options); + expect( + harness.transforms.find( + transform => + transform.descriptor.resourceQuery?.toString() === + String(/\?react-router-route/) + ) + ).toBeUndefined(); + expect( + harness.transforms.find(transform => transform.descriptor.order === 'post') + ).toBeUndefined(); + expect(options.routeTransformExecutor.run).not.toHaveBeenCalledWith( + expect.objectContaining({ kind: 'routeModule' }) + ); + }); + + it('registers route-module transforms through api.transform in source mode', async () => { + const harness = createTransformHarness(); + const options = createBaseOptions(harness, true); + + registerBuildOutputTransforms(options); + const routeModuleTransforms = harness.transforms.filter( transform => transform.descriptor.order === 'post' ); @@ -99,11 +122,6 @@ describe('build output transforms', () => { expect(routeModuleTransforms[1].descriptor).toMatchObject({ order: 'post', }); - expect( - (routeModuleTransforms[1].descriptor.test as (path: string) => boolean)( - options.routePath - ) - ).toBe(true); await routeModuleTransforms[0].handler( createTransformArgs(options.routePath, '?react-router-route') @@ -112,27 +130,26 @@ describe('build output transforms', () => { createTransformArgs(options.routePath) ); - const run = options.routeTransformExecutor.run; - expect(run).toHaveBeenCalledWith( + expect(options.routeTransformExecutor.run).toHaveBeenCalledWith( expect.objectContaining({ kind: 'routeModule' }) ); - expect(run).toHaveBeenCalledTimes(2); + expect(options.routeTransformExecutor.run).toHaveBeenCalledTimes(2); }); - it('does not match queryless route-module transforms for internal route requests', () => { + it('does not match split-export transforms for internal route requests', () => { const harness = createTransformHarness(); const options = createBaseOptions(harness); registerBuildOutputTransforms(options); - const querylessRouteModuleTransform = harness.transforms.find( + const splitExportsTransform = harness.transforms.find( transform => - transform.descriptor.order === 'post' && + transform.descriptor.environments?.includes('web') && typeof transform.descriptor.test === 'function' ); - expect(querylessRouteModuleTransform).toBeDefined(); - const predicate = querylessRouteModuleTransform!.descriptor.test as ( + expect(splitExportsTransform).toBeDefined(); + const predicate = splitExportsTransform!.descriptor.test as ( path: string ) => boolean; expect(predicate(options.routePath)).toBe(true); @@ -140,8 +157,9 @@ describe('build output transforms', () => { false ); - const resourceQuery = querylessRouteModuleTransform!.descriptor - .resourceQuery as { not: RegExp }; + const resourceQuery = splitExportsTransform!.descriptor.resourceQuery as { + not: RegExp; + }; expect(resourceQuery.not.test('?__react-router-build-client-route')).toBe( true ); diff --git a/tests/dev-runtime.integration.test.ts b/tests/dev-runtime.integration.test.ts index 09501fdd..96897fa3 100644 --- a/tests/dev-runtime.integration.test.ts +++ b/tests/dev-runtime.integration.test.ts @@ -1,4 +1,3 @@ -import { EventEmitter } from 'node:events'; import { spawn } from 'node:child_process'; import * as fs from 'node:fs'; import { createServer, type Server as HttpServer } from 'node:http'; @@ -89,18 +88,6 @@ const getBuildMarker = (build: ServerBuild): string | undefined => { return undefined; }; -const createNoopWatcher = (): fs.FSWatcher => { - const watcher = new EventEmitter() as EventEmitter & { - close: () => void; - ref: () => fs.FSWatcher; - unref: () => fs.FSWatcher; - }; - watcher.close = () => undefined; - watcher.ref = () => watcher as fs.FSWatcher; - watcher.unref = () => watcher as fs.FSWatcher; - return watcher as fs.FSWatcher; -}; - const runEsmIntegrationSubprocess = (repositoryRoot: string): Promise => new Promise((resolve, reject) => { const rstestCli = join( @@ -193,9 +180,6 @@ const createDevRuntimeHarness = async (esm: boolean) => { mockRestore?: () => void; }; existsSyncMock.mockRestore?.(); - const watchMock = rstest - .spyOn(fs, 'watch') - .mockImplementation((() => createNoopWatcher()) as typeof fs.watch); const logger = createLogger({ level: 'silent' }); const loggerError = rstest.spyOn(logger, 'error'); const consoleError = rstest @@ -241,7 +225,6 @@ const createDevRuntimeHarness = async (esm: boolean) => { } loggerError.mockRestore(); consoleError.mockRestore(); - watchMock.mockRestore(); rmSync(fixtureRoot, { force: true, recursive: true }); } }; @@ -399,6 +382,8 @@ const createDevRuntimeHarness = async (esm: boolean) => { ), loadBuild, loadRawEntry, + hasDiskOutput: (relativePath: string) => + fs.existsSync(join(fixtureRoot, relativePath)), rebuildRoute: (source: string) => invalidate(source, false), rebuildWebFirst: (source: string) => invalidate(source, true), requestBuiltInDocument, @@ -438,13 +423,15 @@ const expectFirstCommittedGeneration = async ( timeout: 20_000, }) .toBeGreaterThan(completedBeforeRecovery); + await new Promise(resolve => setTimeout(resolve, 250)); - const build = await withTimeout( - harness.loadBuild(), - 5_000, - `the first valid generation after ${harness.compileAttempts} attempts and ${harness.completedCompiles} completions` - ); - expect(getBuildMarker(build)).toBe('v1'); + await expect + .poll(async () => getBuildMarker(await harness.loadBuild()), { + intervals: [50, 100, 250], + timeout: 20_000, + }) + .toBe('v1'); + const build = await harness.loadBuild(); expect(build.assets).toBeTypeOf('object'); expect(build.entry).toBeTypeOf('object'); expect(build.routes).toBeTypeOf('object'); @@ -470,6 +457,14 @@ const expectFirstCommittedGeneration = async ( await expect(harness.loadRawEntry('static/js/app')).resolves.toMatchObject({ customServerMarker: 'custom-server-entry', }); + expect( + harness.hasDiskOutput('build/server/static/js/react-router-server-build.js') + ).toBe(false); + expect( + harness.hasDiskOutput( + 'build/client/static/js/virtual/react-router/browser-manifest.js' + ) + ).toBe(false); await expect(harness.requestDocument()).resolves.toContain('v1'); await harness.startBuiltInServer(); await expect(harness.requestBuiltInDocument()).resolves.toContain('v1'); diff --git a/tests/features.test.ts b/tests/features.test.ts index 6e1489f2..28b505cf 100644 --- a/tests/features.test.ts +++ b/tests/features.test.ts @@ -33,7 +33,7 @@ describe('pluginReactRouter', () => { // The plugin should not override Rsbuild's HMR defaults. expect(config.dev.hmr).toBe(true); expect(config.dev.liveReload).toBe(true); - expect(config.dev.writeToDisk).toBe(true); + expect(config.dev.writeToDisk).toBe(false); }); it('should register the dev server middleware via server.setup', async () => { diff --git a/tests/index.test.ts b/tests/index.test.ts index 617e1683..18431f32 100644 --- a/tests/index.test.ts +++ b/tests/index.test.ts @@ -60,7 +60,7 @@ describe('pluginReactRouter', () => { // The plugin should not override Rsbuild's HMR defaults. expect(config.dev.hmr).toBe(true); expect(config.dev.liveReload).toBe(true); - expect(config.dev.writeToDisk).toBe(true); + expect(config.dev.writeToDisk).toBe(false); expect(config.dev.lazyCompilation).toMatchObject({ entries: true, imports: true, @@ -330,6 +330,34 @@ describe('pluginReactRouter', () => { ).toBe(true); }); + it('preserves user web splitChunks overrides', async () => { + const rsbuild = await createStubRsbuild({ + rsbuildConfig: { + environments: { + web: { + tools: { + rspack: { + optimization: { + splitChunks: { chunks: 'all' }, + }, + }, + }, + }, + }, + }, + }); + + rsbuild.addPlugins([pluginReactRouter()]); + const config = await rsbuild.unwrapConfig(); + + expect( + config.environments?.web?.tools?.rspack?.optimization?.splitChunks + ).toEqual({ chunks: 'all' }); + expect( + config.environments?.web?.tools?.rspack?.optimization?.runtimeChunk + ).toBe('single'); + }); + it('reduces file size reporting overhead for medium split route builds by default', async () => { const restoreEnv = captureEnv([ 'RR_TEST_SPLIT_ROUTE_MODULES', diff --git a/tests/parallel-route-transforms.test.ts b/tests/parallel-route-transforms.test.ts index cdd029aa..29180eaa 100644 --- a/tests/parallel-route-transforms.test.ts +++ b/tests/parallel-route-transforms.test.ts @@ -1,566 +1,39 @@ import { describe, expect, it } from '@rstest/core'; -import { getExportNames } from '../src/export-utils'; import { - executeRouteTransformTask, - type RouteTransformResult, - type RouteClientEntryTransformTask, - type RouteModuleTransformTask, -} from '../src/route-transform-tasks'; -import { - createRouteTransformExecutorForTesting, createRouteTransformExecutor, - getDefaultWorkerCount, + shouldParallelizeRouteTransforms, } from '../src/parallel-route-transforms'; -import type { - WorkerRequest, - WorkerResponse, -} from '../src/parallel-route-transform-protocol'; -import type { RouteChunkConfig } from '../src/route-chunks'; - -const routeChunkConfig: RouteChunkConfig = { - splitRouteModules: true, - appDirectory: '/app', - rootRouteFile: 'root.tsx', -}; - -const disabledRouteChunkConfig: RouteChunkConfig = { - ...routeChunkConfig, - splitRouteModules: false, -}; - -const resourcePath = '/app/routes/demo.tsx'; -const createRouteModuleTask = ( - overrides: Partial> = {} -): RouteModuleTransformTask => ({ - kind: 'routeModule' as const, - code: ` - import { serverValue } from '../server-data.server'; - export async function loader() { return serverValue; } - export default function Route() { return null; } - `, - resource: `${resourcePath}?react-router-route`, - resourcePath, - environmentName: 'web', - sourceMaps: true, - ssr: true, - isBuild: false, - isSpaMode: false, - rootRoutePath: '/app/root.tsx', - ...overrides, -}); - -const createRouteClientEntryTask = ( - overrides: Partial> = {} -): RouteClientEntryTransformTask => ({ - kind: 'routeClientEntry' as const, - code: ` - export async function clientLoader() { return null; } - export default function Route() { return null; } - `, - resourcePath, - environmentName: 'web', - isBuild: true, - routeChunkConfig, - ...overrides, -}); - -type FakeWorkerHandler = (value: any) => void; - -class FakeRouteTransformWorker { - readonly messages: WorkerRequest[] = []; - readonly handlers = new Map(); - failNextPostMessage = false; - terminateCalls = 0; - - on(event: string, handler: FakeWorkerHandler): this { - this.handlers.set(event, [...(this.handlers.get(event) ?? []), handler]); - return this; - } - - postMessage(message: WorkerRequest): void { - if (this.failNextPostMessage) { - this.failNextPostMessage = false; - throw new Error('postMessage failed'); - } - this.messages.push(message); - } - - async terminate(): Promise { - this.terminateCalls += 1; - return 0; - } - - emit(event: string, value: unknown): void { - for (const handler of this.handlers.get(event) ?? []) { - handler(value); - } - } -} - -const resolveWorkerMessage = ( - worker: FakeRouteTransformWorker, - result: RouteTransformResult, - messageIndex = worker.messages.length - 1 -): void => { - worker.emit('message', { - id: worker.messages[messageIndex]!.id, - ok: true, - result, - } satisfies WorkerResponse); -}; - -describe('parallel route transforms', () => { - it.each([ - [1, 0], - [2, 0], - [3, 0], - [4, 0], - [5, 2], - [6, 2], - [8, 2], - [10, 2], - [12, 2], - [24, 2], - ])('caps default worker count by available CPUs', (cpus, workers) => { - expect(getDefaultWorkerCount(cpus)).toBe(workers); - }); - - it.each([ - [1, 0], - [2, 0], - [3, 1], - [4, 2], - [5, 2], - [8, 2], - ])( - 'keeps build workers on small machines (%s CPUs -> %s workers)', - (cpus, workers) => { - expect(getDefaultWorkerCount(cpus, { isBuild: true })).toBe(workers); - } - ); - - it.each([0, Number.NaN, 1.5])( - 'rejects invalid explicit worker count %s', - workerCount => { - expect(() => - createRouteTransformExecutor({ - parallelRouteTransform: workerCount, - }) - ).toThrow('must be true, false, or a positive integer'); - } - ); - - it('honors an explicit worker count', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: 2, - }); - - try { - const result = await executor.run(createRouteModuleTask()); - expect(result.code).toContain('export default _withComponentProps'); - expect(result.code).not.toContain('loader'); - } finally { - await executor.close(); - } +describe('route transform executor', () => { + it('enables Rspack loader parallelism for large route graphs', () => { + expect(shouldParallelizeRouteTransforms(255)).toBe(false); + expect(shouldParallelizeRouteTransforms(256)).toBe(true); }); - it('forces the default worker count with true', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: true, - }); - - try { - const result = await executor.run(createRouteModuleTask()); - - expect(result.code).toContain('export default _withComponentProps'); - expect(result.code).not.toContain('loader'); - } finally { - await executor.close(); - } - }); - - it('runs route builds inline when parallel transforms are disabled', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: false, - }); - - try { - const result = await executor.run(createRouteModuleTask()); - - expect(result.code).toContain('export default _withComponentProps'); - expect(result.code).not.toContain('loader'); - } finally { - await executor.close(); - } - }); + it('runs non-loader route transform tasks inline', async () => { + const executor = createRouteTransformExecutor(); - it('does not create route transform workers until work is scheduled', async () => { - let createdWorkers = 0; - const worker = new FakeRouteTransformWorker(); - const executor = createRouteTransformExecutorForTesting( - { - parallelRouteTransform: 1, - }, - () => { - createdWorkers += 1; - return worker; - } - ); - - expect(createdWorkers).toBe(0); - - const pending = executor.run(createRouteModuleTask()); - expect(createdWorkers).toBe(1); - resolveWorkerMessage(worker, { code: 'created lazily' }); - await expect(pending).resolves.toEqual({ code: 'created lazily' }); - - await executor.close(); - expect(worker.terminateCalls).toBe(1); - }); - - it('rejects in-flight worker tasks on idempotent close and runs inline afterward', async () => { - const worker = new FakeRouteTransformWorker(); - const executor = createRouteTransformExecutorForTesting( - { - parallelRouteTransform: 1, - }, - () => worker - ); - - const pending = executor.run(createRouteModuleTask()); - expect(worker.messages).toHaveLength(1); - - const firstClose = executor.close(); - const secondClose = executor.close(); - - await expect(pending).rejects.toThrow('Route transform worker closed.'); - await expect(Promise.all([firstClose, secondClose])).resolves.toEqual([ - undefined, - undefined, - ]); - expect(worker.terminateCalls).toBe(1); - - const inlineResult = await executor.run(createRouteModuleTask()); - expect(inlineResult.code).toContain('export default _withComponentProps'); - expect(worker.messages).toHaveLength(1); - }); - - it('sends full source again after a cached worker request fails to post', async () => { - const worker = new FakeRouteTransformWorker(); - const executor = createRouteTransformExecutorForTesting( - { - parallelRouteTransform: 1, - }, - () => worker - ); - const task = createRouteModuleTask(); - - const firstRun = executor.run(task); - expect(worker.messages[0]?.task.code).toBe(task.code); - resolveWorkerMessage(worker, { code: 'first' }, 0); - await expect(firstRun).resolves.toEqual({ code: 'first' }); - - worker.failNextPostMessage = true; - await expect(executor.run(task)).rejects.toThrow('postMessage failed'); - - const thirdRun = executor.run(task); - expect(worker.messages[1]?.task.code).toBe(task.code); - resolveWorkerMessage(worker, { code: 'third' }, 1); - await expect(thirdRun).resolves.toEqual({ code: 'third' }); - - await executor.close(); - }); - - it('creates only worker slots that receive scheduled work', async () => { - const workers: FakeRouteTransformWorker[] = []; - const executor = createRouteTransformExecutorForTesting( - { - parallelRouteTransform: 4, - splitRouteModules: true, - }, - () => { - const worker = new FakeRouteTransformWorker(); - workers.push(worker); - return worker; - } - ); - - const first = executor.run(createRouteModuleTask()); - const second = executor.run( - createRouteModuleTask({ resourcePath: '/app/routes/other.tsx' }) - ); - - expect(workers).toHaveLength(2); - - for (const worker of workers) { - resolveWorkerMessage(worker, { code: 'done' }); - } - - await expect(Promise.all([first, second])).resolves.toEqual([ - { code: 'done' }, - { code: 'done' }, - ]); - - await executor.close(); - expect(workers.map(worker => worker.terminateCalls)).toEqual([1, 1]); - }); - - it('keeps related route source transforms on the same worker', async () => { - const workers: FakeRouteTransformWorker[] = []; - const executor = createRouteTransformExecutorForTesting( - { - parallelRouteTransform: 2, - splitRouteModules: true, - }, - () => { - const worker = new FakeRouteTransformWorker(); - workers.push(worker); - return worker; - } - ); - const code = ` - export async function clientLoader() { return null; } - export default function Route() { return null; } - `; - - const clientEntry = executor.run(createRouteClientEntryTask({ code })); - expect(workers).toHaveLength(1); - expect(workers[0]?.messages[0]?.task.code).toBe(code); - resolveWorkerMessage(workers[0]!, { code: 'client' }); - await expect(clientEntry).resolves.toEqual({ code: 'client' }); - - const routeModule = executor.run( - createRouteModuleTask({ - code, - environmentName: 'node', - isBuild: true, - }) - ); - expect(workers).toHaveLength(1); - expect(workers[0]?.messages[1]?.task.code).toBeUndefined(); - resolveWorkerMessage(workers[0]!, { code: 'module' }); - await expect(routeModule).resolves.toEqual({ code: 'module' }); - - await executor.close(); - }); - - it('can prewarm worker slots before the first route transform', async () => { - const workers: FakeRouteTransformWorker[] = []; - const executor = createRouteTransformExecutorForTesting( - { - parallelRouteTransform: 4, - }, - () => { - const worker = new FakeRouteTransformWorker(); - workers.push(worker); - return worker; - } - ); - - executor.prewarm(); - executor.prewarm(); - expect(workers).toHaveLength(4); - - executor.prewarm(); - expect(workers).toHaveLength(4); - - await executor.close(); - expect(workers.map(worker => worker.terminateCalls)).toEqual([ - 1, 1, 1, 1, - ]); - }); - - it('executes route client entry tasks through the shared task executor', async () => { await expect( - executeRouteTransformTask({ - kind: 'routeClientEntry', + executor.run({ + kind: 'routeModule', code: ` export async function loader() { return null; } - export async function clientLoader() { return null; } export default function Route() { return null; } `, - resourcePath, + resource: '/project/app/routes/page.tsx?react-router-route', + resourcePath: '/project/app/routes/page.tsx', environmentName: 'web', + sourceMaps: false, + ssr: true, isBuild: false, - routeChunkConfig: disabledRouteChunkConfig, - }) - ).resolves.toEqual({ - code: `export { clientLoader, default } from "${resourcePath}?react-router-route";`, - }); - }); - - it('can execute route module tasks through worker-backed parallelism', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: 2, - }); - - try { - const result = await executor.run(createRouteModuleTask()); - - expect(result.code).toContain('export default _withComponentProps'); - expect(result.code).not.toContain('loader'); - } finally { - await executor.close(); - } - }); - - it('produces identical build route modules when environments need the same output', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: 2, - splitRouteModules: true, - }); - const task = createRouteModuleTask({ - code: ` - export async function clientLoader() { return null; } - export default function Route() { return null; } - `, - environmentName: 'node', - isBuild: true, - }); - - try { - const nodeResult = await executor.run(task); - const webResult = await executor.run({ - ...task, - environmentName: 'web', - }); - - expect(webResult).toEqual(nodeResult); - } finally { - await executor.close(); - } - }); - - it('keeps environment-specific build route module output isolated', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: 2, - splitRouteModules: true, - }); - const task = createRouteModuleTask({ - environmentName: 'node', - isBuild: true, - }); - - try { - const nodeResult = await executor.run(task); - const webResult = await executor.run({ - ...task, - environmentName: 'web', - }); - - await expect(getExportNames(nodeResult.code)).resolves.toContain( - 'loader' - ); - await expect(getExportNames(webResult.code)).resolves.not.toContain( - 'loader' - ); - } finally { - await executor.close(); - } - }); - - it('isolates escaped server exports across build environments', async () => { - const executor = createRouteTransformExecutor({ - parallelRouteTransform: 2, - splitRouteModules: true, - }); - const task = createRouteModuleTask({ - code: String.raw` - const implementation = async () => null; - export { implementation as lo\u0061der }; - export default function Route() { return null; } - `, - environmentName: 'node', - isBuild: true, - }); - - try { - const nodeResult = await executor.run(task); - const webResult = await executor.run({ - ...task, - environmentName: 'web', - }); - - expect(nodeResult.code).toContain('loader'); - expect(webResult.code).not.toContain('loader'); - } finally { - await executor.close(); - } - }); - - it('preserves runtime TypeScript for the downstream Rsbuild SWC stage', async () => { - const result = await executeRouteTransformTask( - createRouteModuleTask({ - code: ` - export enum Status { Active } - export default function Route() { return Status.Active; } - `, - environmentName: 'node', - isBuild: true, + isSpaMode: false, + rootRoutePath: '/project/app/root.tsx', }) - ); - - expect(result.code).toContain('enum Status'); - expect(result.code).toContain('Status.Active'); - }); - - it('preserves value imports when web route modules have no server-only exports', async () => { - const result = await executeRouteTransformTask( - createRouteModuleTask({ - code: ` - import { setup } from './side-effect'; - export default function Route() { return null; } - `, - environmentName: 'web', - ssr: false, - isBuild: true, - }) - ); - - expect(result.code).toContain(`import { setup } from './side-effect';`); - }); - - it('rejects invalid SPA route module exports from the route transform AST', async () => { - await expect( - executeRouteTransformTask( - createRouteModuleTask({ - code: ` - export async function action() { return null; } - export default function Route() { return null; } - `, - ssr: false, - isSpaMode: true, - }) - ) - ).rejects.toThrow('SPA Mode: 1 invalid route export'); - }); - - it('generates route module source maps when the environment requests them', async () => { - const task = createRouteModuleTask({ - code: ` - export async function loader() { return null; } - export default function Route() { return null; } - `, - }); - - const buildResult = await executeRouteTransformTask({ - ...task, - isBuild: true, + ).resolves.toMatchObject({ + code: expect.stringContaining('export default _withComponentProps'), }); - expect(buildResult.map).not.toBeNull(); - const devResult = await executeRouteTransformTask({ - ...task, - isBuild: false, - }); - - expect(devResult.map).not.toBeNull(); - - const withoutSourceMaps = await executeRouteTransformTask({ - ...task, - sourceMaps: false, - }); - expect(withoutSourceMaps.map).toBeNull(); + expect(() => executor.prewarm()).not.toThrow(); + await expect(executor.close()).resolves.toBeUndefined(); }); }); diff --git a/tests/route-module-transform-loader.test.ts b/tests/route-module-transform-loader.test.ts new file mode 100644 index 00000000..c15d7d34 --- /dev/null +++ b/tests/route-module-transform-loader.test.ts @@ -0,0 +1,64 @@ +import { describe, expect, it } from '@rstest/core'; +import routeModuleTransformLoader, { + type RouteModuleTransformLoaderOptions, +} from '../src/route-module-transform-loader'; + +const defaultOptions: RouteModuleTransformLoaderOptions = { + environmentName: 'web', + ssr: true, + isBuild: false, + isSpaMode: false, + rootRoutePath: '/project/app/root.tsx', +}; + +const runLoader = ( + code: string, + { + options = defaultOptions, + sourceMap = false, + }: { + options?: RouteModuleTransformLoaderOptions; + sourceMap?: boolean; + } = {} +) => + new Promise<{ code: string; map: unknown }>((resolve, reject) => { + const context = { + resource: '/project/app/routes/page.tsx?react-router-route', + resourcePath: '/project/app/routes/page.tsx', + sourceMap, + async: () => (error: Error | null, result?: string, map?: unknown) => { + if (error) { + reject(error); + return; + } + resolve({ code: result ?? '', map }); + }, + getOptions: () => options, + }; + + void routeModuleTransformLoader.call(context as never, code); + }); + +describe('route module transform loader', () => { + it('transforms route modules through the loader API', async () => { + const result = await runLoader(` + export async function loader() { return null; } + export default function Route() { return null; } + `); + + expect(result.code).toContain('export default _withComponentProps'); + expect(result.code).not.toContain('export async function loader'); + expect(result.map).toBeUndefined(); + }); + + it('emits a source map when the loader context requests one', async () => { + const result = await runLoader( + ` + export default function Route() { return null; } + `, + { sourceMap: true } + ); + + expect(result.map).toBeDefined(); + }); +}); From 0efa1fe139348804da43dee5ad95aeb99cf8c80b Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Wed, 8 Jul 2026 21:54:24 +0000 Subject: [PATCH 2/4] Address review findings --- src/build-output-transforms.ts | 16 +-- src/dev-background-resources.ts | 15 +-- src/federation.ts | 37 ++++++ src/index.ts | 129 +++----------------- src/parallel-route-transforms.ts | 21 ++-- src/performance.ts | 32 ++++- src/route-module-transform-loader.ts | 47 +++++-- src/route-module-transform-rules.ts | 101 +++++++++++++++ tests/build-output-transforms.test.ts | 13 +- tests/federation.test.ts | 17 +++ tests/parallel-route-transforms.test.ts | 11 +- tests/route-module-transform-loader.test.ts | 34 +++++- tests/route-module-transform-rules.test.ts | 69 +++++++++++ 13 files changed, 369 insertions(+), 173 deletions(-) create mode 100644 src/federation.ts create mode 100644 src/route-module-transform-rules.ts create mode 100644 tests/federation.test.ts create mode 100644 tests/route-module-transform-rules.test.ts diff --git a/src/build-output-transforms.ts b/src/build-output-transforms.ts index 7038557e..7c149735 100644 --- a/src/build-output-transforms.ts +++ b/src/build-output-transforms.ts @@ -6,7 +6,7 @@ import { getReactRouterManifestForDev, type ReactRouterManifestStats, } from './manifest.js'; -import type { RouteTransformExecutor } from './parallel-route-transforms.js'; +import type { RouteTransformRunner } from './parallel-route-transforms.js'; import type { ReactRouterPerformanceProfiler } from './performance.js'; import { createBundlerRouteExportResolver } from './route-export-resolution.js'; import type { RouteChunkConfig } from './route-chunks.js'; @@ -31,7 +31,7 @@ type RegisterBuildOutputTransformsOptions = { appDirectory: string; getAssetPrefix: () => string; routeChunkOptions: Parameters[5]; - routeTransformExecutor: RouteTransformExecutor; + routeTransformRunner: RouteTransformRunner; routeByFilePath: Map; routeChunkConfig: RouteChunkConfig; isBuild: boolean; @@ -54,7 +54,7 @@ export const registerBuildOutputTransforms = ({ appDirectory, getAssetPrefix, routeChunkOptions, - routeTransformExecutor, + routeTransformRunner, routeByFilePath, routeChunkConfig, isBuild, @@ -70,7 +70,7 @@ export const registerBuildOutputTransforms = ({ 'route:module', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'routeModule', code: args.code, resource: args.resource, @@ -153,7 +153,7 @@ export const registerBuildOutputTransforms = ({ 'route:client-entry', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'routeClientEntry', code: args.code, resourcePath: args.resourcePath, @@ -175,7 +175,7 @@ export const registerBuildOutputTransforms = ({ 'route:chunk', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'routeChunk', code: args.code, resource: args.resource, @@ -201,7 +201,7 @@ export const registerBuildOutputTransforms = ({ 'route:split-exports', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'splitRouteExports', code: args.code, resourcePath: args.resourcePath, @@ -241,7 +241,7 @@ export const registerBuildOutputTransforms = ({ 'module:client-only-stub', args.resource, async () => { - return routeTransformExecutor.run({ + return routeTransformRunner({ kind: 'clientOnlyStub', code: args.code, resourcePath: args.resourcePath, diff --git a/src/dev-background-resources.ts b/src/dev-background-resources.ts index 70d21d98..c1e76f72 100644 --- a/src/dev-background-resources.ts +++ b/src/dev-background-resources.ts @@ -18,7 +18,6 @@ import { configRoutesToRouteManifestEntries, type ReactRouterManifestForDev, } from './manifest.js'; -import type { RouteTransformExecutor } from './parallel-route-transforms.js'; import { createRouteManifestSnapshot, createRouteTopologyWatcher, @@ -31,7 +30,6 @@ type RegisterReactRouterDevBackgroundResourcesOptions = { api: RsbuildPluginAPI; isBuild: boolean; lazyCompilationPrewarm: PluginOptions['unstableLazyCompilationPrewarm']; - routeTransformExecutor: RouteTransformExecutor; routeRestartMarkerPath: string; watchDirectory: string; getRouteTopology: () => Promise>; @@ -135,7 +133,6 @@ export const registerReactRouterDevBackgroundResources = ({ api, isBuild, lazyCompilationPrewarm, - routeTransformExecutor, routeRestartMarkerPath, watchDirectory, getRouteTopology, @@ -213,8 +210,6 @@ export const registerReactRouterDevBackgroundResources = ({ scheduleRouteTopologyWatcher(); lazyCompilationPrewarmController?.schedule(); }); - - routeTransformExecutor.prewarm(); } const closeRouteTopologyWatcher = async (): Promise => { @@ -230,20 +225,12 @@ export const registerReactRouterDevBackgroundResources = ({ ); }; - const closeRouteTransformExecutor = (): Promise => - routeTransformExecutor.close(); - api.onCloseDevServer(() => closeAll( '[rsbuild-plugin-react-router] Failed to close dev server resources.', - [ - closeRouteTopologyWatcher, - closeLazyCompilationPrewarm, - closeRouteTransformExecutor, - ] + [closeRouteTopologyWatcher, closeLazyCompilationPrewarm] ) ); - api.onCloseBuild(closeRouteTransformExecutor); return { setManifest(manifest) { diff --git a/src/federation.ts b/src/federation.ts new file mode 100644 index 00000000..b9840ae1 --- /dev/null +++ b/src/federation.ts @@ -0,0 +1,37 @@ +import type { Rspack } from '@rsbuild/core'; + +type ModuleFederationPluginLike = { + name?: string; + _options?: { experiments?: { asyncStartup?: boolean } }; + options?: { experiments?: { asyncStartup?: boolean } }; +}; + +export const ensureFederationAsyncStartup = ( + rspackConfig: Rspack.Configuration | undefined +): void => { + if (!rspackConfig?.plugins?.length) { + return; + } + + for (const plugin of rspackConfig.plugins) { + if (!plugin || typeof plugin !== 'object') { + continue; + } + const pluginName = (plugin as ModuleFederationPluginLike).name; + if (pluginName !== 'ModuleFederationPlugin') { + continue; + } + + const pluginOptions = + (plugin as ModuleFederationPluginLike)._options ?? + (plugin as ModuleFederationPluginLike).options; + if (!pluginOptions) { + continue; + } + + pluginOptions.experiments = { + ...pluginOptions.experiments, + asyncStartup: true, + }; + } +}; diff --git a/src/index.ts b/src/index.ts index b34f26b8..92ccaeed 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,4 @@ import { existsSync, readFileSync } from 'node:fs'; -import { fileURLToPath } from 'node:url'; import fsExtra from 'fs-extra'; import type { Config } from './react-router-config.js'; import type { RouteConfigEntry } from '@react-router/dev/routes'; @@ -19,6 +18,7 @@ import { PLUGIN_NAME, } from './constants.js'; import { guardReactRouterLazyCompilation } from './lazy-compilation.js'; +import { ensureFederationAsyncStartup } from './federation.js'; import { createReactRouterDevServerSetup } from './dev-server.js'; import { generateWithProps, @@ -53,10 +53,13 @@ import { type RouteChunkConfig, } from './route-chunks.js'; import { - createRouteTransformExecutor, + createRouteTransformRunner, shouldParallelizeRouteTransforms, } from './parallel-route-transforms.js'; -import type { RouteModuleTransformLoaderOptions } from './route-module-transform-loader.js'; +import { + registerRouteModuleTransformRules, + shouldUseApiRouteModuleTransforms, +} from './route-module-transform-rules.js'; import { getRouteRestartMarkerPath, mergeWatchFiles } from './route-watch.js'; import { validateRouteConfig } from './route-config.js'; import { @@ -99,87 +102,11 @@ export const shouldParallelizeEnvironmentBuilds = ({ }): boolean => !isBuild && spareCoreCount >= MIN_PARALLEL_ENVIRONMENT_BUILD_SPARE_CORES; -type ModuleFederationPluginLike = { - name?: string; - _options?: { experiments?: { asyncStartup?: boolean } }; - options?: { experiments?: { asyncStartup?: boolean } }; -}; - -const ensureFederationAsyncStartup = ( - rspackConfig: Rspack.Configuration | undefined -): void => { - if (!rspackConfig?.plugins?.length) { - return; - } - - for (const plugin of rspackConfig.plugins) { - if (!plugin || typeof plugin !== 'object') { - continue; - } - const pluginName = (plugin as ModuleFederationPluginLike).name; - if (pluginName !== 'ModuleFederationPlugin') { - continue; - } - - const pluginOptions = - (plugin as ModuleFederationPluginLike)._options ?? - (plugin as ModuleFederationPluginLike).options; - if (!pluginOptions) { - continue; - } - - pluginOptions.experiments = { - ...pluginOptions.experiments, - asyncStartup: true, - }; - } -}; - const cssUrlAssetExtensions = /\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/; const urlAssetResourceQuery = /^(?=.*(?:\?|&)url(?:&|$))(?!.*(?:\?|&)(?:raw|inline)(?:&|$))/; -const routeModuleTransformLoaderPath = fileURLToPath( - new URL('./route-module-transform-loader.js', import.meta.url) -); -const useApiRouteModuleTransforms = - existsSync( - fileURLToPath( - new URL('./route-module-transform-loader.ts', import.meta.url) - ) - ) || process.env.RSTEST === 'true'; - -const getRouteModuleTransformParallel = ( - parallelRouteTransform: PluginOptions['parallelRouteTransform'] -): Rspack.RuleSetLoaderWithOptions['parallel'] => { - if (parallelRouteTransform === true) { - return true; - } - if (typeof parallelRouteTransform === 'number') { - if ( - !Number.isInteger(parallelRouteTransform) || - parallelRouteTransform < 1 - ) { - throw new Error( - '[react-router] parallelRouteTransform must be true, false, or a positive integer.' - ); - } - return { maxWorkers: parallelRouteTransform }; - } - return undefined; -}; - -const createRouteModuleTransformUse = ( - options: RouteModuleTransformLoaderOptions, - parallelRouteTransform: PluginOptions['parallelRouteTransform'] -): Rspack.RuleSetLoaderWithOptions => { - const parallel = getRouteModuleTransformParallel(parallelRouteTransform); - return { - loader: routeModuleTransformLoaderPath, - options, - ...(parallel ? { parallel } : {}), - }; -}; +const useApiRouteModuleTransforms = shouldUseApiRouteModuleTransforms(); export const pluginReactRouter = ( options: PluginOptions = {} @@ -466,7 +393,7 @@ export const pluginReactRouter = ( const parallelRouteTransform = pluginOptions.parallelRouteTransform ?? shouldParallelizeRouteTransforms(routeCount); - const routeTransformExecutor = createRouteTransformExecutor({ + const routeTransformRunner = createRouteTransformRunner({ routeChunkCache, }); const routeChunkOptions = { @@ -489,7 +416,6 @@ export const pluginReactRouter = ( api, isBuild, lazyCompilationPrewarm: pluginOptions.unstableLazyCompilationPrewarm, - routeTransformExecutor, routeRestartMarkerPath, watchDirectory, getRouteTopology: routeTopology.getRouteTopology, @@ -949,33 +875,16 @@ export const pluginReactRouter = ( tools: { rspack: rspackConfig => { if (!useApiRouteModuleTransforms) { - const routeModuleTransformUse = createRouteModuleTransformUse( - { - environmentName: name, - ssr, - isBuild, - isSpaMode, - rootRoutePath, - }, - parallelRouteTransform - ); - rspackConfig.module ??= {}; - rspackConfig.module.rules ??= []; - rspackConfig.module.rules.push( - { - resourceQuery: /\?react-router-route/, - enforce: 'post', - use: [routeModuleTransformUse], - }, - { - test: path => routeByFilePath.has(path), - resourceQuery: { - not: /__react-router-build-client-route|react-router-route|route-chunk=/, - }, - enforce: 'post', - use: [routeModuleTransformUse], - } - ); + registerRouteModuleTransformRules(rspackConfig, { + environmentName: name, + ssr, + isBuild, + isSpaMode, + rootRoutePath, + logPerformance, + routeByFilePath, + parallelRouteTransform, + }); } if (pluginOptions.federation) { @@ -1046,7 +955,7 @@ export const pluginReactRouter = ( appDirectory, getAssetPrefix: () => assetPrefix, routeChunkOptions, - routeTransformExecutor, + routeTransformRunner, routeByFilePath, routeChunkConfig, isBuild, diff --git a/src/parallel-route-transforms.ts b/src/parallel-route-transforms.ts index 1ef47e22..1f53faf6 100644 --- a/src/parallel-route-transforms.ts +++ b/src/parallel-route-transforms.ts @@ -10,18 +10,13 @@ const AUTO_PARALLEL_ROUTE_THRESHOLD = 256; export const shouldParallelizeRouteTransforms = (routeCount: number): boolean => routeCount >= AUTO_PARALLEL_ROUTE_THRESHOLD; -export type RouteTransformExecutorOptions = RouteTransformTaskOptions; +export type RouteTransformRunnerOptions = RouteTransformTaskOptions; -export type RouteTransformExecutor = { - run: (task: RouteTransformTask) => Promise; - prewarm: () => void; - close: () => Promise; -}; +export type RouteTransformRunner = ( + task: RouteTransformTask +) => Promise; -export const createRouteTransformExecutor = ( - options: RouteTransformExecutorOptions = {} -): RouteTransformExecutor => ({ - run: task => executeRouteTransformTask(task, options), - prewarm: () => {}, - close: async () => {}, -}); +export const createRouteTransformRunner = + (options: RouteTransformRunnerOptions = {}): RouteTransformRunner => + task => + executeRouteTransformTask(task, options); diff --git a/src/performance.ts b/src/performance.ts index f15c8e2e..c5eb2313 100644 --- a/src/performance.ts +++ b/src/performance.ts @@ -57,6 +57,36 @@ export type ReactRouterPerformanceReport = { operations: Record; }; +export const createSingleOperationPerformanceReport = ({ + environment, + operation, + resource, + durationMs, +}: { + environment: string | undefined; + operation: string; + resource: string; + durationMs: number; +}): ReactRouterPerformanceReport => { + const roundedDurationMs = roundMs(durationMs); + return { + environment: environment ?? 'unknown', + operations: { + [operation]: { + count: 1, + totalMs: roundedDurationMs, + wallMs: roundedDurationMs, + maxMs: roundedDurationMs, + slowest: [{ durationMs: roundedDurationMs, resource }], + }, + }, + }; +}; + +export const formatReactRouterPerformanceReport = ( + report: ReactRouterPerformanceReport +): string => `[react-router:performance] ${JSON.stringify(report)}`; + export type ReactRouterPerformanceProfiler = { record( environment: string | undefined, @@ -247,7 +277,7 @@ export const createReactRouterPerformanceProfiler = ({ ...details, operations, }; - log(`[react-router:performance] ${JSON.stringify(report)}`); + log(formatReactRouterPerformanceReport(report)); timingsByEnvironment.delete(resolvedEnvironment); }, }; diff --git a/src/route-module-transform-loader.ts b/src/route-module-transform-loader.ts index 91385cf9..56cc43f0 100644 --- a/src/route-module-transform-loader.ts +++ b/src/route-module-transform-loader.ts @@ -1,8 +1,13 @@ import type { LoaderDefinition } from '@rspack/core'; +import { + createSingleOperationPerformanceReport, + formatReactRouterPerformanceReport, +} from './performance.js'; import { executeRouteTransformTask } from './route-transform-tasks.js'; export type RouteModuleTransformLoaderOptions = { environmentName: string; + logPerformance: boolean; ssr: boolean; isBuild: boolean; isSpaMode: boolean; @@ -22,20 +27,38 @@ const routeModuleTransformLoader: LoaderDefinition { + try { + return await executeRouteTransformTask({ + kind: 'routeModule', + code: String(source), + resource: this.resource, + resourcePath: this.resourcePath, + environmentName: options.environmentName, + sourceMaps: Boolean(this.sourceMap), + ssr: options.ssr, + isBuild: options.isBuild, + isSpaMode: options.isSpaMode, + rootRoutePath: options.rootRoutePath, + }); + } finally { + if (options.logPerformance) { + console.info( + formatReactRouterPerformanceReport( + createSingleOperationPerformanceReport({ + environment: options.environmentName, + operation: 'route:module', + resource: this.resource, + durationMs: performance.now() - startMs, + }) + ) + ); + } + } + })(); callback(null, result.code, result.map ?? undefined); } catch (error) { diff --git a/src/route-module-transform-rules.ts b/src/route-module-transform-rules.ts new file mode 100644 index 00000000..cdf98665 --- /dev/null +++ b/src/route-module-transform-rules.ts @@ -0,0 +1,101 @@ +import { existsSync } from 'node:fs'; +import { fileURLToPath } from 'node:url'; +import type { Rspack } from '@rsbuild/core'; +import type { RouteModuleTransformLoaderOptions } from './route-module-transform-loader.js'; +import type { PluginOptions, Route } from './types.js'; + +const routeModuleTransformLoaderPath = fileURLToPath( + new URL('./route-module-transform-loader.js', import.meta.url) +); + +export const shouldUseApiRouteModuleTransforms = (): boolean => + existsSync( + fileURLToPath( + new URL('./route-module-transform-loader.ts', import.meta.url) + ) + ) || process.env.RSTEST === 'true'; + +const getRouteModuleTransformParallel = ( + parallelRouteTransform: PluginOptions['parallelRouteTransform'] +): Rspack.RuleSetLoaderWithOptions['parallel'] => { + if (parallelRouteTransform === true) { + return true; + } + if (typeof parallelRouteTransform === 'number') { + if ( + !Number.isInteger(parallelRouteTransform) || + parallelRouteTransform < 1 + ) { + throw new Error( + '[react-router] parallelRouteTransform must be true, false, or a positive integer.' + ); + } + return { maxWorkers: parallelRouteTransform }; + } + return undefined; +}; + +const createRouteModuleTransformUse = ( + options: RouteModuleTransformLoaderOptions, + parallelRouteTransform: PluginOptions['parallelRouteTransform'] +): Rspack.RuleSetLoaderWithOptions => { + const parallel = getRouteModuleTransformParallel(parallelRouteTransform); + return { + loader: routeModuleTransformLoaderPath, + options, + ...(parallel ? { parallel } : {}), + }; +}; + +export const registerRouteModuleTransformRules = ( + rspackConfig: Rspack.Configuration, + { + environmentName, + ssr, + isBuild, + isSpaMode, + rootRoutePath, + logPerformance, + routeByFilePath, + parallelRouteTransform, + }: { + environmentName: string; + ssr: boolean; + isBuild: boolean; + isSpaMode: boolean; + rootRoutePath: string | null; + logPerformance: boolean; + routeByFilePath: Map; + parallelRouteTransform: PluginOptions['parallelRouteTransform']; + } +): void => { + const routeModuleTransformUse = createRouteModuleTransformUse( + { + environmentName, + logPerformance, + ssr, + isBuild, + isSpaMode, + rootRoutePath, + }, + parallelRouteTransform + ); + + rspackConfig.module ??= {}; + rspackConfig.module.rules ??= []; + rspackConfig.module.rules.push( + { + resourceQuery: /\?react-router-route/, + enforce: 'post', + use: [routeModuleTransformUse], + }, + { + test: path => routeByFilePath.has(path), + resourceQuery: { + not: /__react-router-build-client-route|react-router-route|route-chunk=/, + }, + enforce: 'post', + use: [routeModuleTransformUse], + } + ); +}; diff --git a/tests/build-output-transforms.test.ts b/tests/build-output-transforms.test.ts index 2cc23aca..9a4109b6 100644 --- a/tests/build-output-transforms.test.ts +++ b/tests/build-output-transforms.test.ts @@ -46,10 +46,9 @@ const createBaseOptions = ( appDirectory, getAssetPrefix: () => '/', routeChunkOptions: { isBuild: true }, - routeTransformExecutor: { - run: rstest.fn(async task => ({ code: `${task.kind}:${task.code}` })), - close: rstest.fn(async () => undefined), - }, + routeTransformRunner: rstest.fn(async task => ({ + code: `${task.kind}:${task.code}`, + })), routeByFilePath: new Map([[routePath, { id: 'page' }]]), routeChunkConfig: { splitRouteModules: true, @@ -99,7 +98,7 @@ describe('build output transforms', () => { expect( harness.transforms.find(transform => transform.descriptor.order === 'post') ).toBeUndefined(); - expect(options.routeTransformExecutor.run).not.toHaveBeenCalledWith( + expect(options.routeTransformRunner).not.toHaveBeenCalledWith( expect.objectContaining({ kind: 'routeModule' }) ); }); @@ -130,10 +129,10 @@ describe('build output transforms', () => { createTransformArgs(options.routePath) ); - expect(options.routeTransformExecutor.run).toHaveBeenCalledWith( + expect(options.routeTransformRunner).toHaveBeenCalledWith( expect.objectContaining({ kind: 'routeModule' }) ); - expect(options.routeTransformExecutor.run).toHaveBeenCalledTimes(2); + expect(options.routeTransformRunner).toHaveBeenCalledTimes(2); }); it('does not match split-export transforms for internal route requests', () => { diff --git a/tests/federation.test.ts b/tests/federation.test.ts new file mode 100644 index 00000000..b53679ca --- /dev/null +++ b/tests/federation.test.ts @@ -0,0 +1,17 @@ +import { describe, expect, it } from '@rstest/core'; +import { ensureFederationAsyncStartup } from '../src/federation'; + +describe('federation helpers', () => { + it('enables async startup on module federation plugins', () => { + const moduleFederationPlugin = { + name: 'ModuleFederationPlugin', + options: { experiments: { asyncStartup: false } }, + }; + + ensureFederationAsyncStartup({ + plugins: [moduleFederationPlugin, { name: 'OtherPlugin' }], + }); + + expect(moduleFederationPlugin.options.experiments.asyncStartup).toBe(true); + }); +}); diff --git a/tests/parallel-route-transforms.test.ts b/tests/parallel-route-transforms.test.ts index 29180eaa..d44ca7e7 100644 --- a/tests/parallel-route-transforms.test.ts +++ b/tests/parallel-route-transforms.test.ts @@ -1,20 +1,20 @@ import { describe, expect, it } from '@rstest/core'; import { - createRouteTransformExecutor, + createRouteTransformRunner, shouldParallelizeRouteTransforms, } from '../src/parallel-route-transforms'; -describe('route transform executor', () => { +describe('route transform runner', () => { it('enables Rspack loader parallelism for large route graphs', () => { expect(shouldParallelizeRouteTransforms(255)).toBe(false); expect(shouldParallelizeRouteTransforms(256)).toBe(true); }); it('runs non-loader route transform tasks inline', async () => { - const executor = createRouteTransformExecutor(); + const routeTransformRunner = createRouteTransformRunner(); await expect( - executor.run({ + routeTransformRunner({ kind: 'routeModule', code: ` export async function loader() { return null; } @@ -32,8 +32,5 @@ describe('route transform executor', () => { ).resolves.toMatchObject({ code: expect.stringContaining('export default _withComponentProps'), }); - - expect(() => executor.prewarm()).not.toThrow(); - await expect(executor.close()).resolves.toBeUndefined(); }); }); diff --git a/tests/route-module-transform-loader.test.ts b/tests/route-module-transform-loader.test.ts index c15d7d34..12293ee6 100644 --- a/tests/route-module-transform-loader.test.ts +++ b/tests/route-module-transform-loader.test.ts @@ -1,10 +1,11 @@ -import { describe, expect, it } from '@rstest/core'; +import { describe, expect, it, rstest } from '@rstest/core'; import routeModuleTransformLoader, { type RouteModuleTransformLoaderOptions, } from '../src/route-module-transform-loader'; const defaultOptions: RouteModuleTransformLoaderOptions = { environmentName: 'web', + logPerformance: false, ssr: true, isBuild: false, isSpaMode: false, @@ -61,4 +62,35 @@ describe('route module transform loader', () => { expect(result.map).toBeDefined(); }); + + it('logs route-module performance reports when enabled', async () => { + const info = rstest.spyOn(console, 'info').mockImplementation(() => {}); + + try { + await runLoader( + ` + export default function Route() { return null; } + `, + { options: { ...defaultOptions, logPerformance: true } } + ); + + expect(info).toHaveBeenCalledTimes(1); + const message = String(info.mock.calls[0][0]); + const prefix = '[react-router:performance] '; + expect(message.startsWith(prefix)).toBe(true); + + const report = JSON.parse(message.slice(prefix.length)); + expect(report.environment).toBe('web'); + expect(report.operations['route:module']).toMatchObject({ + count: 1, + slowest: [ + { + resource: '/project/app/routes/page.tsx?react-router-route', + }, + ], + }); + } finally { + info.mockRestore(); + } + }); }); diff --git a/tests/route-module-transform-rules.test.ts b/tests/route-module-transform-rules.test.ts new file mode 100644 index 00000000..f2b64bb9 --- /dev/null +++ b/tests/route-module-transform-rules.test.ts @@ -0,0 +1,69 @@ +import { describe, expect, it } from '@rstest/core'; +import { registerRouteModuleTransformRules } from '../src/route-module-transform-rules'; + +const createRuleConfig = ( + parallelRouteTransform: boolean | number | undefined +) => { + const routePath = '/project/app/routes/page.tsx'; + const rspackConfig = {}; + + registerRouteModuleTransformRules(rspackConfig, { + environmentName: 'web', + ssr: true, + isBuild: false, + isSpaMode: false, + rootRoutePath: '/project/app/root.tsx', + logPerformance: true, + routeByFilePath: new Map([[routePath, { id: 'page' }]]), + parallelRouteTransform, + }); + + return rspackConfig as { + module: { + rules: Array<{ + test?: (path: string) => boolean; + use: Array<{ + loader: string; + options: Record; + parallel?: true | { maxWorkers: number }; + }>; + }>; + }; + }; +}; + +describe('route module transform rules', () => { + it('registers route module loader rules with loader options', () => { + const config = createRuleConfig(true); + const [queryRule, routeRule] = config.module.rules; + + expect(config.module.rules).toHaveLength(2); + expect(queryRule.use[0]).toMatchObject({ + options: { + environmentName: 'web', + logPerformance: true, + ssr: true, + isBuild: false, + isSpaMode: false, + rootRoutePath: '/project/app/root.tsx', + }, + parallel: true, + }); + expect(routeRule.test?.('/project/app/routes/page.tsx')).toBe(true); + expect(routeRule.test?.('/project/app/routes/other.tsx')).toBe(false); + }); + + it('passes explicit worker counts to Rspack loader parallelism', () => { + const config = createRuleConfig(3); + + expect(config.module.rules[0].use[0].parallel).toEqual({ + maxWorkers: 3, + }); + }); + + it('rejects invalid worker counts', () => { + expect(() => createRuleConfig(0)).toThrow( + '[react-router] parallelRouteTransform must be true, false, or a positive integer.' + ); + }); +}); From 67092d4bc05b177c9391dae9bd976c2161c093b5 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Thu, 9 Jul 2026 00:05:11 +0000 Subject: [PATCH 3/4] Aggregate route module loader performance logs --- src/performance.ts | 26 ---- src/route-module-transform-loader.ts | 125 ++++++++++++++------ src/route-module-transform-rules.ts | 6 + tests/route-module-transform-loader.test.ts | 69 +++++++++-- tests/route-module-transform-rules.test.ts | 1 + 5 files changed, 160 insertions(+), 67 deletions(-) diff --git a/src/performance.ts b/src/performance.ts index c5eb2313..8a9e9b3a 100644 --- a/src/performance.ts +++ b/src/performance.ts @@ -57,32 +57,6 @@ export type ReactRouterPerformanceReport = { operations: Record; }; -export const createSingleOperationPerformanceReport = ({ - environment, - operation, - resource, - durationMs, -}: { - environment: string | undefined; - operation: string; - resource: string; - durationMs: number; -}): ReactRouterPerformanceReport => { - const roundedDurationMs = roundMs(durationMs); - return { - environment: environment ?? 'unknown', - operations: { - [operation]: { - count: 1, - totalMs: roundedDurationMs, - wallMs: roundedDurationMs, - maxMs: roundedDurationMs, - slowest: [{ durationMs: roundedDurationMs, resource }], - }, - }, - }; -}; - export const formatReactRouterPerformanceReport = ( report: ReactRouterPerformanceReport ): string => `[react-router:performance] ${JSON.stringify(report)}`; diff --git a/src/route-module-transform-loader.ts b/src/route-module-transform-loader.ts index 56cc43f0..0cd75dba 100644 --- a/src/route-module-transform-loader.ts +++ b/src/route-module-transform-loader.ts @@ -1,12 +1,10 @@ import type { LoaderDefinition } from '@rspack/core'; -import { - createSingleOperationPerformanceReport, - formatReactRouterPerformanceReport, -} from './performance.js'; +import { createReactRouterPerformanceProfiler } from './performance.js'; import { executeRouteTransformTask } from './route-transform-tasks.js'; export type RouteModuleTransformLoaderOptions = { environmentName: string; + performanceScopeId: string; logPerformance: boolean; ssr: boolean; isBuild: boolean; @@ -20,6 +18,64 @@ type LoaderContextWithSourceMap = ThisParameterType< sourceMap?: boolean; }; +const LOADER_PERFORMANCE_FLUSH_DELAY_MS = 50; + +const routeModuleTransformLoaderPerformanceProfilers = new Map< + string, + ReturnType +>(); +const pendingPerformanceFlushKeys = new Set(); +let performanceFlushTimer: ReturnType | undefined; + +const getPerformanceFlushKey = ( + scopeId: string, + environment: string | undefined +): string => `${scopeId}\0${environment ?? 'unknown'}`; + +const getRouteModuleTransformLoaderPerformanceProfiler = (scopeId: string) => { + let profiler = routeModuleTransformLoaderPerformanceProfilers.get(scopeId); + if (!profiler) { + profiler = createReactRouterPerformanceProfiler({ + enabled: true, + log: message => console.info(message), + }); + routeModuleTransformLoaderPerformanceProfilers.set(scopeId, profiler); + } + return profiler; +}; + +export const flushRouteModuleTransformLoaderPerformance = (): void => { + if (performanceFlushTimer) { + clearTimeout(performanceFlushTimer); + performanceFlushTimer = undefined; + } + + for (const key of pendingPerformanceFlushKeys) { + const [scopeId, environment] = key.split('\0'); + const profiler = + routeModuleTransformLoaderPerformanceProfilers.get(scopeId); + profiler?.flush(environment === 'unknown' ? undefined : environment); + routeModuleTransformLoaderPerformanceProfilers.delete(scopeId); + } + pendingPerformanceFlushKeys.clear(); +}; + +const scheduleRouteModuleTransformLoaderPerformanceFlush = ( + scopeId: string, + environment: string | undefined +): void => { + pendingPerformanceFlushKeys.add(getPerformanceFlushKey(scopeId, environment)); + if (performanceFlushTimer) { + clearTimeout(performanceFlushTimer); + } + performanceFlushTimer = setTimeout( + flushRouteModuleTransformLoaderPerformance, + LOADER_PERFORMANCE_FLUSH_DELAY_MS + ); +}; + +process.once('beforeExit', flushRouteModuleTransformLoaderPerformance); + const routeModuleTransformLoader: LoaderDefinition = async function routeModuleTransformLoader( this: LoaderContextWithSourceMap, @@ -27,42 +83,43 @@ const routeModuleTransformLoader: LoaderDefinition + executeRouteTransformTask({ + kind: 'routeModule', + code: String(source), + resource: this.resource, + resourcePath: this.resourcePath, + environmentName: options.environmentName, + sourceMaps: Boolean(this.sourceMap), + ssr: options.ssr, + isBuild: options.isBuild, + isSpaMode: options.isSpaMode, + rootRoutePath: options.rootRoutePath, + }); try { - const result = await (async () => { - try { - return await executeRouteTransformTask({ - kind: 'routeModule', - code: String(source), - resource: this.resource, - resourcePath: this.resourcePath, - environmentName: options.environmentName, - sourceMaps: Boolean(this.sourceMap), - ssr: options.ssr, - isBuild: options.isBuild, - isSpaMode: options.isSpaMode, - rootRoutePath: options.rootRoutePath, - }); - } finally { - if (options.logPerformance) { - console.info( - formatReactRouterPerformanceReport( - createSingleOperationPerformanceReport({ - environment: options.environmentName, - operation: 'route:module', - resource: this.resource, - durationMs: performance.now() - startMs, - }) - ) - ); - } - } - })(); + const result = options.logPerformance + ? await getRouteModuleTransformLoaderPerformanceProfiler( + options.performanceScopeId + ).record( + options.environmentName, + 'route:module', + this.resource, + transform + ) + : await transform(); callback(null, result.code, result.map ?? undefined); } catch (error) { callback(error instanceof Error ? error : new Error(String(error))); + } finally { + if (options.logPerformance) { + scheduleRouteModuleTransformLoaderPerformanceFlush( + options.performanceScopeId, + options.environmentName + ); + } } }; diff --git a/src/route-module-transform-rules.ts b/src/route-module-transform-rules.ts index cdf98665..19181442 100644 --- a/src/route-module-transform-rules.ts +++ b/src/route-module-transform-rules.ts @@ -72,6 +72,12 @@ export const registerRouteModuleTransformRules = ( const routeModuleTransformUse = createRouteModuleTransformUse( { environmentName, + performanceScopeId: [ + environmentName, + isBuild ? 'build' : 'dev', + ssr ? 'ssr' : 'spa', + rootRoutePath ?? 'rootless', + ].join(':'), logPerformance, ssr, isBuild, diff --git a/tests/route-module-transform-loader.test.ts b/tests/route-module-transform-loader.test.ts index 12293ee6..4e6cb239 100644 --- a/tests/route-module-transform-loader.test.ts +++ b/tests/route-module-transform-loader.test.ts @@ -1,10 +1,12 @@ import { describe, expect, it, rstest } from '@rstest/core'; import routeModuleTransformLoader, { + flushRouteModuleTransformLoaderPerformance, type RouteModuleTransformLoaderOptions, } from '../src/route-module-transform-loader'; const defaultOptions: RouteModuleTransformLoaderOptions = { environmentName: 'web', + performanceScopeId: 'web:dev:ssr:/project/app/root.tsx', logPerformance: false, ssr: true, isBuild: false, @@ -63,7 +65,7 @@ describe('route module transform loader', () => { expect(result.map).toBeDefined(); }); - it('logs route-module performance reports when enabled', async () => { + it('aggregates route-module performance reports when enabled', async () => { const info = rstest.spyOn(console, 'info').mockImplementation(() => {}); try { @@ -73,7 +75,15 @@ describe('route module transform loader', () => { `, { options: { ...defaultOptions, logPerformance: true } } ); + await runLoader( + ` + export default function Route() { return null; } + `, + { options: { ...defaultOptions, logPerformance: true } } + ); + expect(info).not.toHaveBeenCalled(); + flushRouteModuleTransformLoaderPerformance(); expect(info).toHaveBeenCalledTimes(1); const message = String(info.mock.calls[0][0]); const prefix = '[react-router:performance] '; @@ -82,14 +92,59 @@ describe('route module transform loader', () => { const report = JSON.parse(message.slice(prefix.length)); expect(report.environment).toBe('web'); expect(report.operations['route:module']).toMatchObject({ - count: 1, - slowest: [ - { - resource: '/project/app/routes/page.tsx?react-router-route', - }, - ], + count: 2, }); + expect(report.operations['route:module'].slowest[0].resource).toBe( + '/project/app/routes/page.tsx?react-router-route' + ); + } finally { + flushRouteModuleTransformLoaderPerformance(); + info.mockRestore(); + } + }); + + it('keeps route-module performance scopes isolated', async () => { + const info = rstest.spyOn(console, 'info').mockImplementation(() => {}); + + try { + await runLoader( + ` + export default function Route() { return null; } + `, + { + options: { + ...defaultOptions, + logPerformance: true, + performanceScopeId: 'scope-a', + }, + } + ); + await runLoader( + ` + export default function Route() { return null; } + `, + { + options: { + ...defaultOptions, + logPerformance: true, + performanceScopeId: 'scope-b', + }, + } + ); + + flushRouteModuleTransformLoaderPerformance(); + + expect(info).toHaveBeenCalledTimes(2); + for (const call of info.mock.calls) { + const message = String(call[0]); + const report = JSON.parse( + message.slice('[react-router:performance] '.length) + ); + expect(report.environment).toBe('web'); + expect(report.operations['route:module'].count).toBe(1); + } } finally { + flushRouteModuleTransformLoaderPerformance(); info.mockRestore(); } }); diff --git a/tests/route-module-transform-rules.test.ts b/tests/route-module-transform-rules.test.ts index f2b64bb9..e01e603c 100644 --- a/tests/route-module-transform-rules.test.ts +++ b/tests/route-module-transform-rules.test.ts @@ -41,6 +41,7 @@ describe('route module transform rules', () => { expect(queryRule.use[0]).toMatchObject({ options: { environmentName: 'web', + performanceScopeId: 'web:dev:ssr:/project/app/root.tsx', logPerformance: true, ssr: true, isBuild: false, From bd106b955fa2cee50bba1f7a3a90569353e30ad9 Mon Sep 17 00:00:00 2001 From: Zack Jackson <25274700+ScriptedAlchemy@users.noreply.github.com> Date: Thu, 9 Jul 2026 00:32:10 +0000 Subject: [PATCH 4/4] Use API route transforms for production builds --- src/index.ts | 8 ++++++- src/route-module-transform-rules.ts | 8 +++++++ tests/route-module-transform-rules.test.ts | 26 +++++++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/src/index.ts b/src/index.ts index 92ccaeed..77321a93 100644 --- a/src/index.ts +++ b/src/index.ts @@ -59,6 +59,7 @@ import { import { registerRouteModuleTransformRules, shouldUseApiRouteModuleTransforms, + shouldUseApiRouteModuleTransformsForAction, } from './route-module-transform-rules.js'; import { getRouteRestartMarkerPath, mergeWatchFiles } from './route-watch.js'; import { validateRouteConfig } from './route-config.js'; @@ -106,7 +107,7 @@ const cssUrlAssetExtensions = /\.(?:css|less|sass|scss|styl|stylus|pcss|postcss|sss)$/; const urlAssetResourceQuery = /^(?=.*(?:\?|&)url(?:&|$))(?!.*(?:\?|&)(?:raw|inline)(?:&|$))/; -const useApiRouteModuleTransforms = shouldUseApiRouteModuleTransforms(); +const supportsApiRouteModuleTransforms = shouldUseApiRouteModuleTransforms(); export const pluginReactRouter = ( options: PluginOptions = {} @@ -377,6 +378,11 @@ export const pluginReactRouter = ( } const isBuild = api.context.action === 'build'; + const useApiRouteModuleTransforms = + shouldUseApiRouteModuleTransformsForAction({ + isBuild, + supportsApiRouteModuleTransforms, + }); const shouldDependOnWebCompiler = !shouldParallelizeEnvironmentBuilds({ isBuild, }); diff --git a/src/route-module-transform-rules.ts b/src/route-module-transform-rules.ts index 19181442..35a75db3 100644 --- a/src/route-module-transform-rules.ts +++ b/src/route-module-transform-rules.ts @@ -15,6 +15,14 @@ export const shouldUseApiRouteModuleTransforms = (): boolean => ) ) || process.env.RSTEST === 'true'; +export const shouldUseApiRouteModuleTransformsForAction = ({ + isBuild, + supportsApiRouteModuleTransforms, +}: { + isBuild: boolean; + supportsApiRouteModuleTransforms: boolean; +}): boolean => isBuild || supportsApiRouteModuleTransforms; + const getRouteModuleTransformParallel = ( parallelRouteTransform: PluginOptions['parallelRouteTransform'] ): Rspack.RuleSetLoaderWithOptions['parallel'] => { diff --git a/tests/route-module-transform-rules.test.ts b/tests/route-module-transform-rules.test.ts index e01e603c..cf4ddfd9 100644 --- a/tests/route-module-transform-rules.test.ts +++ b/tests/route-module-transform-rules.test.ts @@ -1,5 +1,8 @@ import { describe, expect, it } from '@rstest/core'; -import { registerRouteModuleTransformRules } from '../src/route-module-transform-rules'; +import { + registerRouteModuleTransformRules, + shouldUseApiRouteModuleTransformsForAction, +} from '../src/route-module-transform-rules'; const createRuleConfig = ( parallelRouteTransform: boolean | number | undefined @@ -33,6 +36,27 @@ const createRuleConfig = ( }; describe('route module transform rules', () => { + it('uses api route-module transforms for production builds', () => { + expect( + shouldUseApiRouteModuleTransformsForAction({ + isBuild: true, + supportsApiRouteModuleTransforms: false, + }) + ).toBe(true); + expect( + shouldUseApiRouteModuleTransformsForAction({ + isBuild: false, + supportsApiRouteModuleTransforms: false, + }) + ).toBe(false); + expect( + shouldUseApiRouteModuleTransformsForAction({ + isBuild: false, + supportsApiRouteModuleTransforms: true, + }) + ).toBe(true); + }); + it('registers route module loader rules with loader options', () => { const config = createRuleConfig(true); const [queryRule, routeRule] = config.module.rules;