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 8a0712df..4988e505 100644 --- a/examples/client-only/package.json +++ b/examples/client-only/package.json @@ -20,7 +20,7 @@ "devDependencies": { "@playwright/test": "^1.61.1", "@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 923af6d1..e37c3535 100644 --- a/examples/cloudflare/package.json +++ b/examples/cloudflare/package.json @@ -23,7 +23,7 @@ "@playwright/test": "^1.61.1", "@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 d8da362a..4039805d 100644 --- a/examples/custom-node-server/package.json +++ b/examples/custom-node-server/package.json @@ -30,7 +30,7 @@ "devDependencies": { "@playwright/test": "^1.61.1", "@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 dafe66f5..cbb10e9b 100644 --- a/examples/default-template/package.json +++ b/examples/default-template/package.json @@ -23,7 +23,7 @@ "devDependencies": { "@playwright/test": "^1.61.1", "@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 270e31a1..adaaf6ba 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.61.1", "@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 19a6fd22..edd4fcbb 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.61.1", "@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 8e09e0a1..09a11311 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.61.1", "@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 e9347b8b..27932aa4 100644 --- a/examples/prerender/package.json +++ b/examples/prerender/package.json @@ -21,7 +21,7 @@ "devDependencies": { "@playwright/test": "^1.61.1", "@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 38eb796a..5a63f25b 100644 --- a/examples/spa-mode/package.json +++ b/examples/spa-mode/package.json @@ -21,7 +21,7 @@ "devDependencies": { "@playwright/test": "^1.61.1", "@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 e8130f7a..3dbd9511 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 8827fb90..5ccebeda 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 @@ -61,23 +61,23 @@ importers: 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 @@ -191,20 +191,20 @@ importers: 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.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 @@ -276,11 +276,11 @@ importers: 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.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 @@ -334,11 +334,11 @@ importers: 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.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 @@ -395,14 +395,14 @@ importers: 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.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.1)(@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 @@ -459,17 +459,17 @@ importers: 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.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 @@ -588,11 +588,11 @@ importers: 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 @@ -748,11 +748,11 @@ importers: 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.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) @@ -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)) @@ -970,11 +970,11 @@ importers: 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 @@ -1127,11 +1127,11 @@ importers: 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.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)) @@ -1334,11 +1334,11 @@ importers: 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 @@ -1491,11 +1491,11 @@ importers: 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.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) @@ -1639,11 +1639,11 @@ importers: 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.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 @@ -1718,11 +1718,11 @@ importers: 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.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 @@ -2924,9 +2924,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 +2967,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 +2987,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 +2994,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 +4440,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 +4540,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==} - 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==} + '@rspack/binding-darwin-arm64@2.1.3': + resolution: {integrity: sha512-oOGI0RSL89Ehu9T22rugmfUY9OC2eBqLMeWRYsu7bhlUrjoXeVfGBBSEXCse666BQ1sAiM8hD/k7nqVria/okQ==} 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==} - cpu: [x64] - os: [darwin] - - '@rspack/binding-darwin-x64@2.1.0': - resolution: {integrity: sha512-PJB6n/BaupvfLaErsfvC7q9W07WozkPe2Xw7sQqX6fblK+4tooBp0ZdAtKi76L+U2fR8t8/nQb0Jokco0co7Fg==} + '@rspack/binding-darwin-x64@2.1.3': + resolution: {integrity: sha512-sVqWXNiFTMXAyN362y6IA+eJc8LXZKfHdhEJ/zDuMmRp+u2IvhgaF8tk3vX/OmeB9jydVjySijuiqk8No/FoCA==} 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==} + '@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@1.7.12': - resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==} + '@rspack/binding-linux-arm64-musl@2.1.3': + resolution: {integrity: sha512-flIE7eluz0d21Fn28EVm3vPwoJooOSqtmjLFVSuOMcoCbwV9clfor195oIrAppp/W7dL/3XquFuVfrsa01Jy8Q==} cpu: [arm64] os: [linux] - '@rspack/binding-linux-arm64-musl@2.0.8': - resolution: {integrity: sha512-igjJ43yxWQ72GZqjDDZSSHax9/Vg+6rLMmOvFglTJUkQpB4Tyvu/YjW+WRjYj2xRw6blOjLxUSJWASvuSqqlvg==} - 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==} - cpu: [x64] - os: [linux] - - '@rspack/binding-linux-x64-gnu@2.1.0': - resolution: {integrity: sha512-oE2CMALLdV3QNiA3YYDZ46tDGf+WRlqu/tQ+B79JYKVwt3sI0fpzvgwPNpx/gfRKUyA0phaeYS4kyOEnpltjpA==} - 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==} + '@rspack/binding-linux-x64-gnu@2.1.3': + resolution: {integrity: sha512-lMXjoGKf0SnviH596fmTszgtnXLHmWOoE90G8grG9MvKVa3pelRmfps5ewZL9s8ENf3NXRfOxIhIf/M9as6MqA==} cpu: [x64] os: [linux] - '@rspack/binding-linux-x64-musl@2.1.0': - resolution: {integrity: sha512-lxTFZgsfPPyyIt/DpOH5TK2u1ZROMB+gLp/LWvYBc8FSOtmR0Gl4L/AWmJdM2yqwPfy0hgSkVicf/7k80jHuVQ==} + '@rspack/binding-linux-x64-musl@2.1.3': + resolution: {integrity: sha512-0esT35v7pW2ZsJTMc/zDUHwpNXlPqyUCyuiLJvrAAUcdENrgOVe4DmFrgVJ2hwqI4GjeN1VBnGRJ8c+edAHH5w==} 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==} - cpu: [wasm32] - - '@rspack/binding-wasm32-wasi@2.1.0': - resolution: {integrity: sha512-ZsDDduXaEF1SpyGz2OFuEU9Tzm0pKtbtCYviymiNtQS+3lx6rXyv+FaK0oIWn+gWL+gVNamplxKnNNR2jZsp5w==} + '@rspack/binding-wasm32-wasi@2.1.3': + resolution: {integrity: sha512-UsrDjD59UEP0mhfN/Z+uTc3vLgiUvIr+mn92WC1sbQi9gtZohTYvaQYFhWuMkBqsACGcmZp704JAbbSrVrVYCA==} 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==} - cpu: [arm64] - os: [win32] - - '@rspack/binding-win32-arm64-msvc@2.1.0': - resolution: {integrity: sha512-0uMWAZYgwdkk0ocE4X85w/0BNWT5GaKJTEZDVYxfSYcfVAxJvIsuM0VH/cjRjsQtEeE1rcY7JvJyd0rQ6j0DqA==} + '@rspack/binding-win32-arm64-msvc@2.1.3': + resolution: {integrity: sha512-42RS/SwKBTkNvXIPZXqTn0yEFN8zwGRfRe/ly0GDvPp/KxpLMFWxJmLxgtoLompU+0UCGvV4KpcBENt3oWs6BA==} 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==} - cpu: [x64] - os: [win32] - - '@rspack/binding-win32-x64-msvc@2.0.8': - resolution: {integrity: sha512-7zPs8YCe/ZVJTwd+5lpB0CP0tkn2pONf/T1ycmVY76u21Nrwt8mXQGc/2yH2eWP4B7fikYBr3hGr7mpR2fajqQ==} + '@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.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.0': - resolution: {integrity: sha512-LsXFIOOYDutHk44SAOcVQa5iA7lhYwEbD+nZhgmCiGJvKKh0UIpBj6EAsBsB6omEK5GEXvjDeLFieKgbYW08QQ==} + '@rspack/binding@2.1.3': + resolution: {integrity: sha512-4UGXJqUHmm36tWG1GgFZz3p8sQ5JuSgWI+gq1xPPoihS41uYJL3cXuJnirTeWsmVrusmYZTQhgU3tl3VYGcJYg==} - '@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 +4627,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 +4689,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 +4702,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==} @@ -9429,14 +9250,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 @@ -10027,10 +9848,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==} @@ -11802,7 +11619,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) @@ -11811,7 +11628,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)) @@ -11827,8 +11644,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)))': @@ -11855,9 +11670,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 @@ -11872,13 +11687,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 @@ -11888,7 +11703,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) @@ -11897,7 +11712,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: @@ -11905,11 +11720,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 @@ -11917,11 +11727,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)) @@ -11929,12 +11734,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 @@ -11943,8 +11742,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) @@ -11954,11 +11751,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 @@ -11976,27 +11768,6 @@ 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)': - 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)': - 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 @@ -13460,33 +13231,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) @@ -13495,11 +13249,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 @@ -13507,30 +13261,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 @@ -13538,41 +13292,41 @@ 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.1)(@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)) + '@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.1) browserslist-load-config: 1.0.3 es-toolkit: 1.49.0 @@ -13590,10 +13344,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 @@ -13601,15 +13355,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.1)(@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.1)(@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' @@ -13619,12 +13373,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 @@ -13636,20 +13390,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) @@ -13667,10 +13421,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: @@ -13678,184 +13432,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': - optional: true - - '@rspack/binding-darwin-x64@1.7.12': - optional: true - - '@rspack/binding-darwin-x64@2.0.8': - optional: true - - '@rspack/binding-darwin-x64@2.1.0': - optional: true - - '@rspack/binding-linux-arm64-gnu@1.7.12': - optional: true - - '@rspack/binding-linux-arm64-gnu@2.0.8': - optional: true - - '@rspack/binding-linux-arm64-gnu@2.1.0': - optional: true - - '@rspack/binding-linux-arm64-musl@1.7.12': - 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': + '@rspack/binding-darwin-arm64@2.1.3': optional: true - '@rspack/binding-linux-x64-gnu@1.7.12': + '@rspack/binding-darwin-x64@2.1.3': optional: true - '@rspack/binding-linux-x64-gnu@2.0.8': + '@rspack/binding-linux-arm64-gnu@2.1.3': optional: true - '@rspack/binding-linux-x64-gnu@2.1.0': + '@rspack/binding-linux-arm64-musl@2.1.3': optional: true - '@rspack/binding-linux-x64-musl@1.7.12': + '@rspack/binding-linux-riscv64-gnu@2.1.3': optional: true - '@rspack/binding-linux-x64-musl@2.0.8': + '@rspack/binding-linux-riscv64-musl@2.1.3': optional: true - '@rspack/binding-linux-x64-musl@2.1.0': + '@rspack/binding-linux-x64-gnu@2.1.3': 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) + '@rspack/binding-linux-x64-musl@2.1.3': 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 + '@rspack/binding@2.1.3': 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-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/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 - 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 @@ -13908,17 +13551,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 @@ -14390,14 +14035,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': @@ -15688,7 +15333,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: {} @@ -17339,11 +16985,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: @@ -18615,10 +18261,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 @@ -19296,8 +18942,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: 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 9b14d0ec..c424a919 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,11 +31,12 @@ type RegisterBuildOutputTransformsOptions = { appDirectory: string; getAssetPrefix: () => string; routeChunkOptions: Parameters[5]; - routeTransformExecutor: RouteTransformExecutor; + routeTransformRunner: RouteTransformRunner; routeByFilePath: Map; routeChunkConfig: RouteChunkConfig; isBuild: boolean; splitRouteModules: boolean; + useApiRouteModuleTransforms: boolean; ssr: boolean; isSpaMode: boolean; rootRoutePath: string; @@ -54,11 +55,12 @@ export const registerBuildOutputTransforms = ({ appDirectory, getAssetPrefix, routeChunkOptions, - routeTransformExecutor, + routeTransformRunner, routeByFilePath, routeChunkConfig, isBuild, splitRouteModules, + useApiRouteModuleTransforms, ssr, isSpaMode, rootRoutePath, @@ -70,7 +72,7 @@ export const registerBuildOutputTransforms = ({ 'route:module', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'routeModule', code: args.code, resource: args.resource, @@ -154,7 +156,7 @@ export const registerBuildOutputTransforms = ({ 'route:client-entry', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'routeClientEntry', code: args.code, resourcePath: args.resourcePath, @@ -178,7 +180,7 @@ export const registerBuildOutputTransforms = ({ 'route:chunk', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'routeChunk', code: args.code, resource: args.resource, @@ -204,7 +206,7 @@ export const registerBuildOutputTransforms = ({ 'route:split-exports', args.resource, async () => - routeTransformExecutor.run({ + routeTransformRunner({ kind: 'splitRouteExports', code: args.code, resourcePath: args.resourcePath, @@ -244,7 +246,7 @@ export const registerBuildOutputTransforms = ({ 'module:client-only-stub', args.resource, async () => { - return routeTransformExecutor.run({ + return routeTransformRunner({ kind: 'clientOnlyStub', code: args.code, resourcePath: args.resourcePath, @@ -257,22 +259,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..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,10 +210,6 @@ export const registerReactRouterDevBackgroundResources = ({ scheduleRouteTopologyWatcher(); lazyCompilationPrewarmController?.schedule(); }); - - // Spawn transform workers now so thread startup overlaps Rsbuild's own - // compiler creation instead of delaying the first route transform. - routeTransformExecutor.prewarm(); } const closeRouteTopologyWatcher = async (): Promise => { @@ -232,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 7144c910..1bd9bc3c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -18,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, @@ -52,9 +53,14 @@ import { type RouteChunkConfig, } from './route-chunks.js'; import { - createRouteTransformExecutor, + createRouteTransformRunner, shouldParallelizeRouteTransforms, } from './parallel-route-transforms.js'; +import { + registerRouteModuleTransformRules, + shouldUseApiRouteModuleTransforms, + shouldUseApiRouteModuleTransformsForAction, +} from './route-module-transform-rules.js'; import { getRouteRestartMarkerPath, mergeWatchFiles } from './route-watch.js'; import { validateRouteConfig } from './route-config.js'; import { @@ -106,46 +112,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 supportsApiRouteModuleTransforms = shouldUseApiRouteModuleTransforms(); export const pluginReactRouter = ( options: PluginOptions = {} @@ -416,6 +387,11 @@ export const pluginReactRouter = ( } const isBuild = api.context.action === 'build'; + const useApiRouteModuleTransforms = + shouldUseApiRouteModuleTransformsForAction({ + isBuild, + supportsApiRouteModuleTransforms, + }); const shouldDependOnWebCompiler = !shouldParallelizeEnvironmentBuilds({ isBuild, }); @@ -429,13 +405,11 @@ export const pluginReactRouter = ( rootRouteFile, }; const routeChunkCache: RouteChunkCache = new Map(); - const routeTransformExecutor = createRouteTransformExecutor({ - parallelRouteTransform: - pluginOptions.parallelRouteTransform ?? - shouldParallelizeRouteTransforms(routeCount), + const parallelRouteTransform = + pluginOptions.parallelRouteTransform ?? + shouldParallelizeRouteTransforms(routeCount); + const routeTransformRunner = createRouteTransformRunner({ routeChunkCache, - splitRouteModules: Boolean(splitRouteModules), - isBuild, }); const routeChunkOptions = { splitRouteModules, @@ -457,7 +431,6 @@ export const pluginReactRouter = ( api, isBuild, lazyCompilationPrewarm: pluginOptions.unstableLazyCompilationPrewarm, - routeTransformExecutor, routeRestartMarkerPath, watchDirectory, getRouteTopology: routeTopology.getRouteTopology, @@ -783,7 +756,6 @@ export const pluginReactRouter = ( routeCount >= 256 && (config.performance?.printFileSize === undefined || config.performance.printFileSize === true); - return mergeRsbuildConfig(config, { ...(shouldCompactFileSizeReport ? { @@ -800,7 +772,6 @@ export const pluginReactRouter = ( assetPrefix: config.output?.assetPrefix || '/', }, dev: { - writeToDisk: true, ...lazyCompilation, watchFiles: mergeWatchFiles(config.dev?.watchFiles, routeWatchFiles), }, @@ -944,6 +915,19 @@ export const pluginReactRouter = ( return mergeEnvironmentConfig(config, { tools: { rspack: rspackConfig => { + if (!useApiRouteModuleTransforms) { + registerRouteModuleTransformRules(rspackConfig, { + environmentName: name, + ssr, + isBuild, + isSpaMode, + rootRoutePath, + logPerformance, + routeByFilePath, + parallelRouteTransform, + }); + } + if (pluginOptions.federation) { ensureFederationAsyncStartup(rspackConfig); } @@ -1024,11 +1008,12 @@ export const pluginReactRouter = ( appDirectory, getAssetPrefix: () => assetPrefix, routeChunkOptions, - routeTransformExecutor, + routeTransformRunner, routeByFilePath, 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..1f53faf6 100644 --- a/src/parallel-route-transforms.ts +++ b/src/parallel-route-transforms.ts @@ -1,458 +1,22 @@ -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; -}; - -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(); -}; - -const createInlineRouteTransformExecutor = ( - options: RouteTransformTaskOptions -): 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); - } +export type RouteTransformRunnerOptions = RouteTransformTaskOptions; - return new ParallelRouteTransformExecutor( - workerCount, - options, - Boolean(splitRouteModules), - createWorker - ); -}; +export type RouteTransformRunner = ( + task: RouteTransformTask +) => Promise; -export const createRouteTransformExecutorForTesting = ( - options: RouteTransformExecutorOptions, - createWorker: RouteTransformWorkerFactory -): RouteTransformExecutor => - createRouteTransformExecutorWithWorkerFactory(options, createWorker); +export const createRouteTransformRunner = + (options: RouteTransformRunnerOptions = {}): RouteTransformRunner => + task => + executeRouteTransformTask(task, options); diff --git a/src/performance.ts b/src/performance.ts index f15c8e2e..8a9e9b3a 100644 --- a/src/performance.ts +++ b/src/performance.ts @@ -57,6 +57,10 @@ export type ReactRouterPerformanceReport = { operations: Record; }; +export const formatReactRouterPerformanceReport = ( + report: ReactRouterPerformanceReport +): string => `[react-router:performance] ${JSON.stringify(report)}`; + export type ReactRouterPerformanceProfiler = { record( environment: string | undefined, @@ -247,7 +251,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 new file mode 100644 index 00000000..0cd75dba --- /dev/null +++ b/src/route-module-transform-loader.ts @@ -0,0 +1,126 @@ +import type { LoaderDefinition } from '@rspack/core'; +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; + isSpaMode: boolean; + rootRoutePath: string | null; +}; + +type LoaderContextWithSourceMap = ThisParameterType< + LoaderDefinition +> & { + 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, + source + ) { + const callback = this.async(); + const options = this.getOptions(); + + const transform = () => + 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 = 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 + ); + } + } + }; + +export default routeModuleTransformLoader; diff --git a/src/route-module-transform-rules.ts b/src/route-module-transform-rules.ts new file mode 100644 index 00000000..35a75db3 --- /dev/null +++ b/src/route-module-transform-rules.ts @@ -0,0 +1,115 @@ +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'; + +export const shouldUseApiRouteModuleTransformsForAction = ({ + isBuild, + supportsApiRouteModuleTransforms, +}: { + isBuild: boolean; + supportsApiRouteModuleTransforms: boolean; +}): boolean => isBuild || supportsApiRouteModuleTransforms; + +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, + performanceScopeId: [ + environmentName, + isBuild ? 'build' : 'dev', + ssr ? 'ssr' : 'spa', + rootRoutePath ?? 'rootless', + ].join(':'), + 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/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 efefeaab..af01bd6a 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'); @@ -45,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, @@ -57,6 +57,7 @@ const createBaseOptions = ( }, isBuild: true, splitRouteModules: true, + useApiRouteModuleTransforms, ssr: true, isSpaMode: false, rootRoutePath: resolve(appDirectory, 'root.tsx'), @@ -81,12 +82,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.routeTransformRunner).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 +121,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,16 +129,15 @@ describe('build output transforms', () => { createTransformArgs(options.routePath) ); - const run = options.routeTransformExecutor.run; - expect(run).toHaveBeenCalledWith( + expect(options.routeTransformRunner).toHaveBeenCalledWith( expect.objectContaining({ kind: 'routeModule' }) ); - expect(run).toHaveBeenCalledTimes(2); + expect(options.routeTransformRunner).toHaveBeenCalledTimes(2); }); it('reads dev HMR enablement when route transforms run', async () => { const harness = createTransformHarness(); - const options = createBaseOptions(harness); + const options = createBaseOptions(harness, true); let devHmrEnabled = false; registerBuildOutputTransforms({ @@ -138,30 +154,30 @@ describe('build output transforms', () => { devHmrEnabled = true; await routeModuleTransform!.handler(createTransformArgs(options.routePath)); - expect(options.routeTransformExecutor.run).toHaveBeenNthCalledWith( + expect(options.routeTransformRunner).toHaveBeenNthCalledWith( 1, expect.objectContaining({ devHmr: false }) ); - expect(options.routeTransformExecutor.run).toHaveBeenNthCalledWith( + expect(options.routeTransformRunner).toHaveBeenNthCalledWith( 2, expect.objectContaining({ devHmr: true }) ); }); - 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); @@ -169,8 +185,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/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/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 4ddbb724..d44ca7e7 100644 --- a/tests/parallel-route-transforms.test.ts +++ b/tests/parallel-route-transforms.test.ts @@ -1,722 +1,36 @@ 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, + createRouteTransformRunner, + 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); +describe('route transform runner', () => { + it('enables Rspack loader parallelism for large route graphs', () => { + expect(shouldParallelizeRouteTransforms(255)).toBe(false); + expect(shouldParallelizeRouteTransforms(256)).toBe(true); }); - 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(); - } - }); - - 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('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); + it('runs non-loader route transform tasks inline', async () => { + const routeTransformRunner = createRouteTransformRunner(); - 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', + routeTransformRunner({ + 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, + isSpaMode: false, + rootRoutePath: '/project/app/root.tsx', }) - ).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, - }) - ); - - 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, - }); - 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(); - }); - - // These pin `collectUnregisteredComponentNames` (route-transform-tasks.ts, - // the dev-HMR $RefreshReg$ backfill for pre-lowered JSX, e.g. MDX routes) - // against react-refresh/babel's own component-detection ruleset - // (react-refresh/cjs/react-refresh-babel.development.js). The heuristic is - // now aligned with that ruleset: single-declarator gate, curried-arrow bail, - // require*/import*/Import callee rejection, first-argument recursion for - // wrapping calls, and a runtime guard that matches `register()`'s own - // function-or-exotic-object acceptance. - describe('dev HMR $RefreshReg$ backfill for pre-lowered routes', () => { - const devHmrTask = ( - code: string, - overrides: Partial> = {} - ) => - createRouteModuleTask({ - code, - devHmr: true, - environmentName: 'web', - isBuild: false, - ...overrides, - }); - - it('registers a top-level function declaration component (matches babel)', async () => { - const result = await executeRouteTransformTask( - devHmrTask(`export function App(){return null}`) - ); - - expect(result.code).toContain('$RefreshReg$(App, "App")'); - }); - - it('registers a single-declarator arrow-fn const referenced as default export (matches babel)', async () => { - const result = await executeRouteTransformTask( - devHmrTask(`const Foo = () => null; export default Foo;`) - ); - - expect(result.code).toContain('$RefreshReg$(Foo, "Foo")'); - }); - - it('skips a multi-declarator export entirely (aligned with react-refresh as of this change)', async () => { - // Babel's react-refresh visitor only registers a VariableDeclaration - // when it has exactly one declarator. We now bail on the whole - // declaration too, so neither `A` (componentish) nor `B` is registered. - const result = await executeRouteTransformTask( - devHmrTask(`export const A = ()=>null, B = 2;`) - ); - - expect(result.code).not.toContain('$RefreshReg$(A, "A")'); - expect(result.code).not.toContain('$RefreshReg$(B, "B")'); - }); - - it('rejects a CallExpression init whose argument is not a component (aligned with react-refresh as of this change)', async () => { - // Babel recurses into the call's first argument and only registers - // when it resolves to a component (fn expr / componentish identifier / - // nested call). We now recurse the first argument too, so an HOC-like - // call with a plain string argument such as `createBox('div')` is no - // longer a false positive. - const result = await executeRouteTransformTask( - devHmrTask(`const Layout = createBox('div'); export default Layout;`) - ); - - expect(result.code).not.toContain('$RefreshReg$(Layout, "Layout")'); - }); - - it('emits a memo()-wrapped component registration that fires at runtime (aligned with react-refresh as of this change)', async () => { - // We collect `Card` and emit a guarded `$RefreshReg$` call. The guard - // now also accepts non-null objects, so the `memo`/`forwardRef` exotic - // object registers -- matching react-refresh's runtime `register()`, - // which tags functions and `$$typeof` exotic objects alike. - const result = await executeRouteTransformTask( - devHmrTask( - `import { memo } from 'react'; const Card = memo(()=>null); export default Card;` - ) - ); - - expect(result.code).toContain( - "if (typeof Card === 'function' || (typeof Card === 'object' && Card !== null)) $RefreshReg$(Card, \"Card\");" - ); - }); - - it('rejects a require/interop-wrapped init (aligned with react-refresh as of this change)', async () => { - // Babel excludes CallExpression inits whose callee is - // `require*`/`import*`/`Import`, and otherwise only registers when the - // first argument resolves to a component. We now do both, so - // `_interopRequireDefault(x)` -- whose lowercase `x` argument is not - // componentish -- is rejected. - const result = await executeRouteTransformTask( - devHmrTask( - `const Fragment = _interopRequireDefault(x); export default Fragment;` - ) - ); - - expect(result.code).not.toContain('$RefreshReg$(Fragment, "Fragment")'); - }); - - it('registers an inline `export default function Route(){}` (matches babel, not via the collector\'s own export-default handling)', async () => { - // NOTE: collectUnregisteredComponentNames never inspects - // ExportDefaultDeclaration itself, so in isolation it would miss this - // case. In the real pipeline it still matches babel here because - // transformRoute() runs *before* the refresh backfill and rewrites - // `export default function Route(){}` into a bare `function Route(){}` - // declaration plus a separate `export default - // _withComponentProps(Route)` statement -- so the bare function - // declaration is picked up by the FunctionDeclaration branch instead. - const result = await executeRouteTransformTask( - devHmrTask(`export default function Route(){return null}`) - ); - - expect(result.code).toContain('$RefreshReg$(Route, "Route")'); - }); - - it('skips class components and non-function capitalized constants (matches babel)', async () => { - const classDecl = await executeRouteTransformTask( - devHmrTask(`class App{ render(){ return null } } export default App;`) - ); - expect(classDecl.code).not.toContain('$RefreshReg$'); - - const classExpr = await executeRouteTransformTask( - devHmrTask(`const App = class{}; export default App;`) - ); - expect(classExpr.code).not.toContain('$RefreshReg$'); - - const nonFnConst = await executeRouteTransformTask( - devHmrTask( - `export const N = 5; export default function Other(){return null}` - ) - ); - expect(nonFnConst.code).not.toContain('$RefreshReg$(N, "N")'); - expect(nonFnConst.code).toContain('$RefreshReg$(Other, "Other")'); - }); - - it('subtracts components already registered via an existing $RefreshReg$ call (matches babel/SWC dedupe)', async () => { - const result = await executeRouteTransformTask( - devHmrTask( - `function App(){return null} $RefreshReg$(_c, "App"); export default App;` - ) - ); - - // Only the pre-existing call should be present; no backfill block - // should be appended for a name that is already registered. - expect(result.code).not.toContain( - "if (typeof $RefreshReg$ === 'function')" - ); - }); - - it('bails on a curried arrow (aligned with react-refresh as of this change)', async () => { - // Babel breaks out of registration when the arrow's body is itself an - // arrow function (a curried component factory, not a component). We now - // apply the same bail, so the outer arrow's identifier is not - // registered. - const result = await executeRouteTransformTask( - devHmrTask(`const A = () => () => null; export default A;`) - ); - - expect(result.code).not.toContain('$RefreshReg$(A, "A")'); + ).resolves.toMatchObject({ + code: expect.stringContaining('export default _withComponentProps'), }); }); }); diff --git a/tests/route-module-transform-loader.test.ts b/tests/route-module-transform-loader.test.ts new file mode 100644 index 00000000..4e6cb239 --- /dev/null +++ b/tests/route-module-transform-loader.test.ts @@ -0,0 +1,151 @@ +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, + 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(); + }); + + it('aggregates 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 } } + ); + 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] '; + 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: 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 new file mode 100644 index 00000000..cf4ddfd9 --- /dev/null +++ b/tests/route-module-transform-rules.test.ts @@ -0,0 +1,94 @@ +import { describe, expect, it } from '@rstest/core'; +import { + registerRouteModuleTransformRules, + shouldUseApiRouteModuleTransformsForAction, +} 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('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; + + expect(config.module.rules).toHaveLength(2); + expect(queryRule.use[0]).toMatchObject({ + options: { + environmentName: 'web', + performanceScopeId: 'web:dev:ssr:/project/app/root.tsx', + 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.' + ); + }); +});