diff --git a/.changeset/rspack-2-node-guard.md b/.changeset/rspack-2-node-guard.md new file mode 100644 index 000000000..60465c312 --- /dev/null +++ b/.changeset/rspack-2-node-guard.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Raise a clear error when running the Rspack-based commands with Rspack 2 on Node.js older than 20.19 (Rspack 2 requires Node `^20.19.0 || >=22.12.0`), instead of failing with `ERR_REQUIRE_ESM`. Rspack commands are now loaded lazily so the version check runs before `@rspack/core` is touched. diff --git a/.github/workflows/test-main-matrix.yml b/.github/workflows/test-main-matrix.yml index a8aca0218..d40d6357d 100644 --- a/.github/workflows/test-main-matrix.yml +++ b/.github/workflows/test-main-matrix.yml @@ -7,6 +7,9 @@ on: - 'website/**' workflow_dispatch: +permissions: + contents: read + jobs: test_main_matrix: name: Tests [Node ${{ matrix.node_version }}] @@ -24,5 +27,9 @@ jobs: with: node-version: ${{ matrix.node_version }} + # Rspack 2 requires Node ^20.19.0 || >=22.12.0, so the older Node + # lanes run the repack unit suite against Rspack 1 - name: Run tests run: pnpm test + env: + RSPACK_MAJOR: ${{ contains(fromJSON('["18", "20"]'), matrix.node_version) && '1' || '2' }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 32d0fcf46..b1777c63d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -10,6 +10,9 @@ on: - 'website/**' workflow_dispatch: +permissions: + contents: read + jobs: lint: name: Lint @@ -53,3 +56,39 @@ jobs: - name: Run tests run: pnpm test + + test_pr_rspack1: + name: Tests [Rspack 1] + if: github.event_name == 'pull_request' + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + - name: Setup workspace + uses: ./.github/actions/setup-pnpm-node + with: + node-version: '24' + + - name: Run tests against Rspack 1 + run: pnpm turbo run test:rspack1 + + test_pr_windows: + name: Tests [Windows] + if: github.event_name == 'pull_request' + runs-on: windows-latest + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # tag=v4.2.2 + - name: Setup workspace + uses: ./.github/actions/setup-pnpm-node + with: + node-version: '24' + + # the require(esm) loading path of @rspack/core@2 and the version + # helpers' filesystem resolution are Windows-sensitive - run the + # repack unit suite under both majors + - name: Run repack tests + run: pnpm turbo run test --filter @callstack/repack + + - name: Run repack tests against Rspack 1 + run: pnpm turbo run test:rspack1 diff --git a/packages/repack/babel.config.js b/packages/repack/babel.config.js index c64d92ff5..aa23bd69b 100644 --- a/packages/repack/babel.config.js +++ b/packages/repack/babel.config.js @@ -31,6 +31,10 @@ module.exports = { // Transform everything in `test` environment, so unit test can pass. test: { presets: [['@babel/preset-env', { targets: { node: 18 } }]], + // The build keeps `import(...)` untransformed (see the override above), + // but Jest runs modules as CJS, so tests need `import(...)` lowered + // to `require(...)` as well. + plugins: ['@babel/plugin-transform-dynamic-import'], }, }, }; diff --git a/packages/repack/jest.config.js b/packages/repack/jest.config.js index 950eee740..b9857e366 100644 --- a/packages/repack/jest.config.js +++ b/packages/repack/jest.config.js @@ -2,8 +2,9 @@ module.exports = { clearMocks: true, moduleNameMapper: { '^(\\.{1,2}/.*)\\.js$': '$1', + '^@rspack/core$': '/jest.rspack-core-bridge.js', }, setupFiles: ['./jest.setup.js'], - testEnvironment: 'node', + testEnvironment: '/jest.environment.js', testMatch: ['**/__tests__/**/*.ts?(x)'], }; diff --git a/packages/repack/jest.environment.js b/packages/repack/jest.environment.js new file mode 100644 index 000000000..d4846842a --- /dev/null +++ b/packages/repack/jest.environment.js @@ -0,0 +1,32 @@ +const { TestEnvironment: NodeEnvironment } = require('jest-environment-node'); + +/** + * @rspack/core v2 is published as a pure ESM package, which Jest's sandboxed + * CJS module runtime cannot load (even `createRequire` inside the sandbox is + * wrapped by Jest and loops back into the module registry). + * + * Test environments are loaded outside the Jest sandbox with Node's real + * module system, where loading ESM through `require()`/`import()` is + * supported. Load @rspack/core here and expose it to the sandbox via a + * global - see jest.rspack-core-bridge.js for the consuming side. + * + * The environment is parameterized on RSPACK_MAJOR (default 2) so the suite + * can run against both supported Rspack majors: + * - v2: `await import('@rspack/core')` (ESM-only package), + * - v1: plain `require` of the aliased `@rspack/core-v1` devDependency - the + * package is CJS, and requiring it directly sidesteps any reliance on + * cjs-module-lexer named-export synthesis. + * `__RSPACK_MAJOR__` is exposed alongside so tests can gate major-specific + * assertions. + */ +class RspackCoreEnvironment extends NodeEnvironment { + async setup() { + await super.setup(); + const major = Number(process.env.RSPACK_MAJOR ?? '2'); + this.global.__RSPACK_CORE__ = + major === 1 ? require('@rspack/core-v1') : await import('@rspack/core'); + this.global.__RSPACK_MAJOR__ = major; + } +} + +module.exports = RspackCoreEnvironment; diff --git a/packages/repack/jest.rspack-core-bridge.js b/packages/repack/jest.rspack-core-bridge.js new file mode 100644 index 000000000..39703a0c1 --- /dev/null +++ b/packages/repack/jest.rspack-core-bridge.js @@ -0,0 +1,18 @@ +// @rspack/core v2 is published as a pure ESM package, which Jest's sandboxed +// CJS module runtime cannot load. The real module is loaded natively by the +// custom test environment (jest.environment.js) and exposed via a global; +// this bridge maps `require('@rspack/core')` inside tests onto it. +// +// The `__esModule` marker keeps Babel's import interop treating this as an +// ESM-like namespace, so named imports (`import { rspack } from '@rspack/core'`) +// keep working. +const core = globalThis.__RSPACK_CORE__; + +if (!core) { + throw new Error( + '@rspack/core was not preloaded by the test environment - ' + + 'make sure jest.environment.js is set as the testEnvironment' + ); +} + +module.exports = { __esModule: true, ...core, default: core.default ?? core }; diff --git a/packages/repack/package.json b/packages/repack/package.json index fb5ccced7..3a385bbdb 100644 --- a/packages/repack/package.json +++ b/packages/repack/package.json @@ -56,6 +56,7 @@ "build:ts": "tsc -p tsconfig.build.json --emitDeclarationOnly", "build": "pnpm run \"/^build:.*/\"", "test": "jest", + "test:rspack1": "cross-env RSPACK_MAJOR=1 jest", "typecheck": "tsc --noEmit", "archive": "pnpm build && pnpm pack", "clang-format": "pnpm clang-format:ios && pnpm clang-format:android", @@ -109,12 +110,14 @@ "devDependencies": { "@babel/cli": "^7.29.7", "@babel/core": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.24.7", "@babel/plugin-transform-export-namespace-from": "^7.29.7", "@babel/plugin-transform-modules-commonjs": "^7.29.7", "@module-federation/enhanced": "0.8.9", "@module-federation/sdk": "0.6.10", - "@rspack/core": "catalog:", - "@swc/helpers": "catalog:", + "@rspack/core": "^2.1.2", + "@rspack/core-v1": "npm:@rspack/core@^1.7.12", + "@swc/helpers": "^0.5.23", "@types/babel__core": "^7.20.5", "@types/dedent": "^0.7.0", "@types/gradient-string": "^1.1.6", @@ -128,6 +131,7 @@ "@types/shallowequal": "^1.1.1", "babel-jest": "^29.7.0", "clang-format": "^1.8.0", + "cross-env": "^7.0.3", "jest": "^29.7.0", "react": "catalog:", "react-native": "catalog:", diff --git a/packages/repack/src/__tests__/rspackTestLane.test.ts b/packages/repack/src/__tests__/rspackTestLane.test.ts new file mode 100644 index 000000000..a5fbed3bb --- /dev/null +++ b/packages/repack/src/__tests__/rspackTestLane.test.ts @@ -0,0 +1,10 @@ +import { rspackVersion } from '@rspack/core'; + +// Guards the dual-major test wiring itself: the custom Jest environment +// (jest.environment.js) loads @rspack/core v2 by default and the aliased +// @rspack/core-v1 under RSPACK_MAJOR=1. If the env var stops being honored, +// the "v1 lane" silently tests v2 twice - this catches that. +test('the loaded @rspack/core major matches the requested RSPACK_MAJOR lane', () => { + const requested = Number(process.env.RSPACK_MAJOR ?? '2'); + expect(Number(rspackVersion.split('.')[0])).toBe(requested); +}); diff --git a/packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts b/packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts new file mode 100644 index 000000000..ae35c0ca2 --- /dev/null +++ b/packages/repack/src/commands/common/__tests__/resetPersistentCache.test.ts @@ -0,0 +1,40 @@ +import { getRspackCacheConfigs } from '../resetPersistentCache.js'; + +describe('getRspackCacheConfigs', () => { + it('should return the legacy experiments.cache config (Rspack 1)', () => { + const cache = { type: 'persistent' as const }; + expect(getRspackCacheConfigs({ experiments: { cache } })).toEqual([cache]); + }); + + it('should return the top-level cache config (Rspack 2)', () => { + const cache = { + type: 'persistent' as const, + storage: { type: 'filesystem' as const, directory: '.cache/custom' }, + }; + expect(getRspackCacheConfigs({ cache })).toEqual([cache]); + }); + + it('should collect both locations when a config carries both keys', () => { + // e.g. a dual-major config or defaults merged with a user config - + // which location is active depends on the installed Rspack major, + // so both need to be considered when resetting the cache + const legacyCache = { type: 'persistent' as const }; + const cache = { + type: 'persistent' as const, + storage: { type: 'filesystem' as const, directory: '.cache/custom' }, + }; + expect( + getRspackCacheConfigs({ cache, experiments: { cache: legacyCache } }) + ).toEqual([legacyCache, cache]); + }); + + it('should fall back to a single entry when no cache config is present', () => { + expect(getRspackCacheConfigs({})).toEqual([undefined]); + expect(getRspackCacheConfigs({ experiments: {} })).toEqual([undefined]); + }); + + it('should keep boolean cache configs', () => { + expect(getRspackCacheConfigs({ cache: true })).toEqual([true]); + expect(getRspackCacheConfigs({ cache: false })).toEqual([false]); + }); +}); diff --git a/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts b/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts index 89d2e06c2..8f4c92e91 100644 --- a/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts +++ b/packages/repack/src/commands/common/__tests__/resolveProjectPath.test.ts @@ -1,3 +1,4 @@ +import path from 'node:path'; import { resolveProjectPath } from '../resolveProjectPath.js'; describe('resolveProjectPath', () => { @@ -6,7 +7,9 @@ describe('resolveProjectPath', () => { expected: string, root = '/project/root' ) => { - expect(resolveProjectPath(input, root)).toBe(expected); + // path.resolve makes the expectation platform-agnostic - on Windows the + // resolved paths carry a drive letter and win32 separators + expect(resolveProjectPath(input, root)).toBe(path.resolve(expected)); }; it('should resolve [projectRoot] prefix correctly', () => { @@ -41,4 +44,30 @@ describe('resolveProjectPath', () => { '/a/b/c/d/e/f' ); }); + + it('should resolve correctly when up-level navigation reaches the filesystem root', () => { + // regression: string-replace + path.join composition produced UNC-like + // `\\...` paths on Windows once the `../` navigation collapsed rootDir + // to the bare filesystem root + expectResolved('[projectRoot^1]/src/index.js', '/src/index.js', '/project'); + expectResolved('[projectRoot^2]/index.js', '/index.js', '/project/root'); + expectResolved('[projectRoot^4]/index.js', '/index.js', '/a/b'); + }); + + it('should stay inside the project root on duplicated separators', () => { + // regression: a leading separator in the remainder made path.resolve + // treat it as an absolute path, escaping rootDir and dropping the + // [projectRoot^N] up-segments entirely + expectResolved('[projectRoot]//src/index.js', '/project/root/src/index.js'); + expectResolved( + '[projectRoot]/src//nested///index.js', + '/project/root/src/nested/index.js' + ); + expectResolved('[projectRoot^1]//src/index.js', '/project/src/index.js'); + expectResolved( + '[projectRoot^2]//shared/utils.js', + '/deep/shared/utils.js', + '/deep/nested/project' + ); + }); }); diff --git a/packages/repack/src/commands/common/resetPersistentCache.ts b/packages/repack/src/commands/common/resetPersistentCache.ts index 53dac9a59..933b1bee7 100644 --- a/packages/repack/src/commands/common/resetPersistentCache.ts +++ b/packages/repack/src/commands/common/resetPersistentCache.ts @@ -4,11 +4,39 @@ import type { Configuration as RspackConfiguration } from '@rspack/core'; import * as colorette from 'colorette'; import type { Configuration as WebpackConfiguration } from 'webpack'; -type RspackCacheOptions = NonNullable< +// Rspack 2 moved the persistent cache configuration from `experiments.cache` +// to the top-level `cache` option (same shape). The v2 types no longer +// declare the legacy location, so extend them with it to support configs +// written for either major. +type RspackCacheOptions = RspackConfiguration['cache']; +type RspackExperimentsWithLegacyCache = NonNullable< RspackConfiguration['experiments'] ->['cache']; +> & { cache?: RspackCacheOptions }; + +export interface RspackConfigurationWithLegacyCache { + cache?: RspackCacheOptions; + experiments?: RspackExperimentsWithLegacyCache; +} + type WebpackCacheOptions = WebpackConfiguration['cache']; +/** + * Collects the persistent cache configurations from a Rspack config, + * covering both the Rspack 1 (`experiments.cache`) and + * Rspack 2 (top-level `cache`) locations. A merged or dual-major config + * can carry both keys and which one is active depends on the installed + * Rspack major, so `--reset-cache` clears both locations. + */ +export function getRspackCacheConfigs( + config: RspackConfigurationWithLegacyCache +): RspackCacheOptions[] { + const cacheConfigs = [config.experiments?.cache, config.cache].filter( + (cacheConfig) => cacheConfig !== undefined + ); + // without an explicit cache config, the default cache location still applies + return cacheConfigs.length > 0 ? cacheConfigs : [undefined]; +} + function getDefaultCacheDirectory( bundler: 'rspack' | 'webpack', rootDir: string @@ -31,6 +59,7 @@ function getRspackCachePaths( for (const cacheConfig of cacheConfigs) { if ( typeof cacheConfig === 'object' && + cacheConfig !== null && 'storage' in cacheConfig && cacheConfig.storage?.directory ) { diff --git a/packages/repack/src/commands/common/resolveProjectPath.ts b/packages/repack/src/commands/common/resolveProjectPath.ts index f5c293aa9..2c30cf765 100644 --- a/packages/repack/src/commands/common/resolveProjectPath.ts +++ b/packages/repack/src/commands/common/resolveProjectPath.ts @@ -13,7 +13,14 @@ export function resolveProjectPath(filepath: string, rootDir: string) { if (!match) return filepath; const [prefix, upLevels] = match; - const upPath = '../'.repeat(Number(upLevels ?? 0)); - const rootPath = path.join(rootDir, upPath); - return path.resolve(filepath.replace(prefix, rootPath)); + const upSegments = Array.from({ length: Number(upLevels ?? 0) }, () => '..'); + const restSegments = filepath + .slice(prefix.length + 1) + .split('/') + .filter(Boolean); + // resolve segment-by-segment instead of string-replace + join composition: + // on Windows, joining enough `../` segments to reach the filesystem root + // yields a bare root ending in a separator, and concatenating the rest of + // the path after it produced a double-separator (UNC-like `\\...`) prefix + return path.resolve(rootDir, ...upSegments, ...restSegments); } diff --git a/packages/repack/src/commands/rspack/__tests__/commandsModuleLoad.test.ts b/packages/repack/src/commands/rspack/__tests__/commandsModuleLoad.test.ts new file mode 100644 index 000000000..908816a92 --- /dev/null +++ b/packages/repack/src/commands/rspack/__tests__/commandsModuleLoad.test.ts @@ -0,0 +1,32 @@ +// Loading '@rspack/core' at require time would crash with ERR_REQUIRE_ESM +// on Node versions unsupported by Rspack 2, before the Node compatibility +// guard has a chance to run. This mock turns any eager load into a test +// failure. Note that bundle.js/start.js are deliberately NOT mocked here, +// so this fails if the commands module ever imports them eagerly again. +jest.mock('@rspack/core', () => { + throw new Error( + '@rspack/core must not be loaded when the rspack commands module is imported' + ); +}); + +describe('rspack commands module', () => { + it('registers commands without loading @rspack/core', () => { + expect(() => require('../index.js')).not.toThrow(); + }); + + it('exposes the expected commands', () => { + const commands: typeof import('../index.js').default = + require('../index.js').default; + + expect(commands.map((command) => command.name)).toEqual([ + 'bundle', + 'webpack-bundle', + 'start', + 'webpack-start', + ]); + + for (const command of commands) { + expect(typeof command.func).toBe('function'); + } + }); +}); diff --git a/packages/repack/src/commands/rspack/__tests__/ensureNodeCompat.test.ts b/packages/repack/src/commands/rspack/__tests__/ensureNodeCompat.test.ts new file mode 100644 index 000000000..548f542a6 --- /dev/null +++ b/packages/repack/src/commands/rspack/__tests__/ensureNodeCompat.test.ts @@ -0,0 +1,72 @@ +import { CLIError, getRspackVersion } from '../../../helpers/index.js'; +import { ensureNodeSupportsRspack } from '../ensureNodeCompat.js'; + +jest.mock('../../../helpers/index.js', () => ({ + ...jest.requireActual( + '../../../helpers/index.js' + ), + getRspackVersion: jest.fn(), +})); + +const getRspackVersionMock = jest.mocked(getRspackVersion); + +// `process.versions.node` is a read-only property, so it cannot be +// mocked with `jest.replaceProperty` - redefine it manually instead. +const originalNodeVersion = Object.getOwnPropertyDescriptor( + process.versions, + 'node' +); + +const setup = (rspackVersion: string | null, nodeVersion: string) => { + getRspackVersionMock.mockReturnValue(rspackVersion); + Object.defineProperty(process.versions, 'node', { + value: nodeVersion, + configurable: true, + }); +}; + +afterAll(() => { + if (originalNodeVersion) { + Object.defineProperty(process.versions, 'node', originalNodeVersion); + } +}); + +describe('ensureNodeSupportsRspack', () => { + it('does nothing when @rspack/core is not resolvable', () => { + setup(null, '18.20.0'); + expect(() => ensureNodeSupportsRspack()).not.toThrow(); + }); + + it('does nothing for Rspack 1.x regardless of Node version', () => { + setup('1.5.8', '18.20.0'); + expect(() => ensureNodeSupportsRspack()).not.toThrow(); + }); + + it.each(['18.20.0', '20.18.3', '21.7.3', '22.11.0'])( + 'throws CLIError for Rspack 2 on unsupported Node %s', + (nodeVersion) => { + setup('2.0.0', nodeVersion); + expect(() => ensureNodeSupportsRspack()).toThrow(CLIError); + } + ); + + it.each(['20.19.0', '20.19.4', '22.12.0', '24.0.0'])( + 'does nothing for Rspack 2 on supported Node %s', + (nodeVersion) => { + setup('2.0.0', nodeVersion); + expect(() => ensureNodeSupportsRspack()).not.toThrow(); + } + ); + + it('treats prerelease Rspack 2 versions as Rspack 2', () => { + setup('2.0.0-beta.1', '18.20.0'); + expect(() => ensureNodeSupportsRspack()).toThrow(CLIError); + }); + + it('reports both the Rspack and Node versions in the error', () => { + setup('2.0.0', '18.20.0'); + expect(() => ensureNodeSupportsRspack()).toThrow( + /Rspack 2\.0\.0 requires Node\.js .+ found 18\.20\.0/ + ); + }); +}); diff --git a/packages/repack/src/commands/rspack/__tests__/lazyCommands.test.ts b/packages/repack/src/commands/rspack/__tests__/lazyCommands.test.ts new file mode 100644 index 000000000..03fde5adf --- /dev/null +++ b/packages/repack/src/commands/rspack/__tests__/lazyCommands.test.ts @@ -0,0 +1,94 @@ +import type { + BundleArguments, + CliConfig, + StartArguments, +} from '../../types.js'; +import { bundle } from '../bundle.js'; +import { ensureNodeSupportsRspack } from '../ensureNodeCompat.js'; +import commands from '../index.js'; +import { start } from '../start.js'; + +// safety net: any code path that loads '@rspack/core' fails loudly +jest.mock('@rspack/core', () => { + throw new Error( + '@rspack/core must not be loaded before the Node compatibility guard runs' + ); +}); + +jest.mock('../ensureNodeCompat.js', () => ({ + ensureNodeSupportsRspack: jest.fn(), +})); +jest.mock('../bundle.js', () => ({ bundle: jest.fn() })); +jest.mock('../start.js', () => ({ start: jest.fn() })); + +const guardMock = jest.mocked(ensureNodeSupportsRspack); +const bundleMock = jest.mocked(bundle); +const startMock = jest.mocked(start); + +const [bundleCommand, webpackBundleCommand, startCommand, webpackStartCommand] = + commands; + +const cliConfig: CliConfig = { + root: '/project', + platforms: ['ios', 'android'], + reactNativePath: '/project/node_modules/react-native', +}; + +const bundleArgs: BundleArguments = { platform: 'ios', dev: true }; +const startArgs: StartArguments = { host: '' }; + +describe('lazy rspack commands', () => { + it.each([ + ['bundle', bundleCommand], + ['webpack-bundle', webpackBundleCommand], + ] as const)( + '%s runs the Node compatibility guard before delegating to bundle', + async (_name, command) => { + await command.func([], cliConfig, bundleArgs); + + expect(guardMock).toHaveBeenCalledTimes(1); + expect(bundleMock).toHaveBeenCalledWith([], cliConfig, bundleArgs); + expect(guardMock.mock.invocationCallOrder[0]).toBeLessThan( + bundleMock.mock.invocationCallOrder[0] + ); + } + ); + + it.each([ + ['start', startCommand], + ['webpack-start', webpackStartCommand], + ] as const)( + '%s runs the Node compatibility guard before delegating to start', + async (_name, command) => { + await command.func([], cliConfig, startArgs); + + expect(guardMock).toHaveBeenCalledTimes(1); + expect(startMock).toHaveBeenCalledWith([], cliConfig, startArgs); + expect(guardMock.mock.invocationCallOrder[0]).toBeLessThan( + startMock.mock.invocationCallOrder[0] + ); + } + ); + + it('does not run bundle when the guard throws', async () => { + guardMock.mockImplementationOnce(() => { + throw new Error('Rspack 2.0.0 requires Node.js ^20.19.0 || >=22.12.0'); + }); + + await expect(bundleCommand.func([], cliConfig, bundleArgs)).rejects.toThrow( + 'Rspack 2.0.0 requires Node.js' + ); + expect(bundleMock).not.toHaveBeenCalled(); + }); + + it('does not run start when the guard throws', async () => { + guardMock.mockImplementationOnce(() => { + throw new Error('Rspack 2.0.0 requires Node.js ^20.19.0 || >=22.12.0'); + }); + + await expect(startCommand.func([], cliConfig, startArgs)).rejects.toThrow( + 'Rspack 2.0.0 requires Node.js' + ); + expect(startMock).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/repack/src/commands/rspack/bundle.ts b/packages/repack/src/commands/rspack/bundle.ts index 6c0975144..2b89a1cef 100644 --- a/packages/repack/src/commands/rspack/bundle.ts +++ b/packages/repack/src/commands/rspack/bundle.ts @@ -4,6 +4,7 @@ import { CLIError } from '../../helpers/index.js'; import { makeCompilerConfig } from '../common/config/makeCompilerConfig.js'; import { getMaxWorkers, + getRspackCacheConfigs, normalizeStatsOptions, resetPersistentCache, setupEnvironment, @@ -25,17 +26,15 @@ export async function bundle( cliConfig: CliConfig, args: BundleArguments ) { - const [config] = await makeCompilerConfig({ - args: args, - bundler: 'rspack', - command: 'bundle', - rootDir: cliConfig.root, - platforms: [args.platform], - reactNativePath: cliConfig.reactNativePath, - }); - - // remove devServer configuration to avoid schema validation errors - delete config.devServer; + const [{ devServer: _devServer, ...config }] = + await makeCompilerConfig({ + args: args, + bundler: 'rspack', + command: 'bundle', + rootDir: cliConfig.root, + platforms: [args.platform], + reactNativePath: cliConfig.reactNativePath, + }); // expose selected args as environment variables setupEnvironment(args); @@ -51,7 +50,7 @@ export async function bundle( resetPersistentCache({ bundler: 'rspack', rootDir: cliConfig.root, - cacheConfigs: [config.experiments?.cache], + cacheConfigs: getRspackCacheConfigs(config), }); } @@ -86,6 +85,9 @@ export async function bundle( } }; + // `devServer` is split off above - it's not needed for bundling, and + // Re.Pack's own dev server options (augmented onto `Configuration`) are + // not assignable to Rspack's bundled `DevServer` type const compiler = rspack(config); return new Promise((resolve) => { diff --git a/packages/repack/src/commands/rspack/ensureNodeCompat.ts b/packages/repack/src/commands/rspack/ensureNodeCompat.ts new file mode 100644 index 000000000..f17d30704 --- /dev/null +++ b/packages/repack/src/commands/rspack/ensureNodeCompat.ts @@ -0,0 +1,31 @@ +import semver from 'semver'; +import { CLIError, getRspackVersion } from '../../helpers/index.js'; + +// Rspack 2 is published as a pure ESM package and declares +// engines.node: "^20.19.0 || >=22.12.0" - the versions where +// loading ESM through require() is supported. +const RSPACK_2_NODE_RANGE = '^20.19.0 || >=22.12.0'; + +/** + * Fails fast with an actionable error when the installed Rspack major + * requires a newer Node.js version than the current one. + * + * Without this guard, loading `@rspack/core` v2 on an unsupported Node + * version crashes with an obscure `ERR_REQUIRE_ESM` error. + */ +export function ensureNodeSupportsRspack() { + const rspackVersion = getRspackVersion(); + + // not resolvable - let the import of '@rspack/core' surface its own error + if (!rspackVersion) return; + + if (semver.major(semver.coerce(rspackVersion) ?? '0.0.0') < 2) return; + + if (semver.satisfies(process.versions.node, RSPACK_2_NODE_RANGE)) return; + + throw new CLIError( + `Rspack ${rspackVersion} requires Node.js ^20.19.0 || >=22.12.0 - ` + + `found ${process.versions.node}. ` + + 'Upgrade Node.js or use @rspack/core@1 instead.' + ); +} diff --git a/packages/repack/src/commands/rspack/index.ts b/packages/repack/src/commands/rspack/index.ts index 7db45a291..6161d7bb7 100644 --- a/packages/repack/src/commands/rspack/index.ts +++ b/packages/repack/src/commands/rspack/index.ts @@ -1,31 +1,50 @@ import { bundleCommandOptions, startCommandOptions } from '../options.js'; -import { bundle } from './bundle.js'; -import { start } from './start.js'; + +import type { bundle } from './bundle.js'; +import type { start } from './start.js'; + +// The command modules load '@rspack/core' which is ESM-only in Rspack 2, +// so they are imported lazily: first the Node version guard runs and turns +// an unsupported setup into an actionable error instead of ERR_REQUIRE_ESM, +// and loading the project config stays free of bundler imports. +const lazyBundle = async (...args: Parameters) => { + const { ensureNodeSupportsRspack } = await import('./ensureNodeCompat.js'); + ensureNodeSupportsRspack(); + const { bundle } = await import('./bundle.js'); + return bundle(...args); +}; + +const lazyStart = async (...args: Parameters) => { + const { ensureNodeSupportsRspack } = await import('./ensureNodeCompat.js'); + ensureNodeSupportsRspack(); + const { start } = await import('./start.js'); + return start(...args); +}; const commands = [ { name: 'bundle', description: 'Build the bundle for the provided JavaScript entry file.', options: bundleCommandOptions, - func: bundle, + func: lazyBundle, }, { name: 'webpack-bundle', description: 'Build the bundle for the provided JavaScript entry file.', options: bundleCommandOptions, - func: bundle, + func: lazyBundle, }, { name: 'start', description: 'Start the React Native development server.', options: startCommandOptions, - func: start, + func: lazyStart, }, { name: 'webpack-start', description: 'Start the React Native development server.', options: startCommandOptions, - func: start, + func: lazyStart, }, ] as const; diff --git a/packages/repack/src/commands/rspack/profile/index.ts b/packages/repack/src/commands/rspack/profile/index.ts index ca88f0856..d75220b5a 100644 --- a/packages/repack/src/commands/rspack/profile/index.ts +++ b/packages/repack/src/commands/rspack/profile/index.ts @@ -1,14 +1,14 @@ -import { rspackVersion } from '@rspack/core'; +import { getRspackVersion } from '../../../helpers/index.js'; -function getRspackVersion() { +function getInstalledRspackVersion() { // get rid of `-beta`, `-rc` etc. - const version = rspackVersion.split('-')[0]; + const version = (getRspackVersion() ?? '0.0.0').split('-')[0]; const [major, minor, patch] = version.split('.').map(Number); return { major, minor, patch }; } async function getProfilingHandler() { - const { major, minor } = getRspackVersion(); + const { major, minor } = getInstalledRspackVersion(); if (major > 1 || (major === 1 && minor >= 4)) { return await import('./profile-1.4.js'); } diff --git a/packages/repack/src/commands/rspack/start.ts b/packages/repack/src/commands/rspack/start.ts index dc915ab4f..9e786f53d 100644 --- a/packages/repack/src/commands/rspack/start.ts +++ b/packages/repack/src/commands/rspack/start.ts @@ -1,4 +1,4 @@ -import type { Configuration } from '@rspack/core'; +import type { Configuration, MultiRspackOptions } from '@rspack/core'; import packageJson from '../../../package.json'; import { VERBOSE_ENV_KEY } from '../../env.js'; import { CLIError, isTruthyEnv } from '../../helpers/index.js'; @@ -14,6 +14,7 @@ import { getDevMiddleware, getMaxWorkers, getMimeType, + getRspackCacheConfigs, parseUrl, resetPersistentCache, resolveProjectPath, @@ -83,7 +84,7 @@ export async function start( resetPersistentCache({ bundler: 'rspack', rootDir: cliConfig.root, - cacheConfigs: configs.map((config) => config.experiments?.cache), + cacheConfigs: configs.flatMap(getRspackCacheConfigs), }); } @@ -96,7 +97,21 @@ export async function start( ); } - const compiler = new Compiler(configs, reporter, cliConfig.root); + // CAST - no clean solution available here: + // Re.Pack augments `Configuration.devServer` with its own dev server options + // (src/types/dev-server-options.d.ts), while Rspack 2 types `devServer` with + // its bundled `DevServer` type. The two are structurally incompatible solely + // because each pulls `proxy` types from a different copy of + // http-proxy-middleware, so no narrowing or `satisfies` can bridge them. + // Unlike `bundle`, `devServer` cannot be stripped from the config here - + // the dev server flow reads it back from `compiler.options`. At runtime + // Rspack accepts & preserves the key (validation is permissive, verified + // in agent_context/rspackv2-jul2026/07-verification-results.md). + const compiler = new Compiler( + configs as unknown as MultiRspackOptions, + reporter, + cliConfig.root + ); const { createServer } = await import('@callstack/repack-dev-server'); const { start, stop } = await createServer({ diff --git a/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts b/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts index c6413754c..605018841 100644 --- a/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts +++ b/packages/repack/src/loaders/babelSwcLoader/__tests__/swc.test.ts @@ -1,5 +1,6 @@ -import { type SwcLoaderOptions, experiments } from '@rspack/core'; +import { experiments } from '@rspack/core'; import { buildFinalSwcConfig, partitionTransforms } from '../babelSwcLoader.js'; +import type { SwcConfig } from '../options.js'; import { addSwcComplementaryTransforms, getSupportedSwcConfigurableTransforms, @@ -84,7 +85,7 @@ describe('swc transforms support detection', () => { const { transformNames } = getSupportedSwcConfigurableTransforms( transforms, - baseSwcConfig as SwcLoaderOptions + baseSwcConfig as SwcConfig ); expect(transformNames).toEqual([ @@ -104,7 +105,7 @@ describe('swc transforms support detection', () => { ['transform-class-properties', { loose: true }], ['transform-private-methods', { loose: true }], ], - {} as SwcLoaderOptions + {} as SwcConfig ); expect(swcConfig.jsc?.assumptions).toEqual({ @@ -114,7 +115,7 @@ describe('swc transforms support detection', () => { }); it('applies loose mode to setSpreadProperties when not defined; preserves explicit true (snapshot)', () => { - const baseUndefined = {} as SwcLoaderOptions; + const baseUndefined = {} as SwcConfig; const { swcConfig: cfg1 } = getSupportedSwcConfigurableTransforms( [['transform-object-rest-spread', { loose: true }]], baseUndefined @@ -124,9 +125,9 @@ describe('swc transforms support detection', () => { 'object-rest-spread loose: setSpreadProperties' ); - const baseTrue: SwcLoaderOptions = { + const baseTrue: SwcConfig = { jsc: { assumptions: { setSpreadProperties: true } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig: cfg2 } = getSupportedSwcConfigurableTransforms( [['transform-object-rest-spread', { loose: false }]], baseTrue @@ -138,9 +139,9 @@ describe('swc transforms support detection', () => { }); it('sets optional-chaining/nullish and for-of assumptions with loose mode and respects explicit values (snapshot)', () => { - const base: SwcLoaderOptions = { + const base: SwcConfig = { jsc: { assumptions: { noDocumentAll: true } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig } = getSupportedSwcConfigurableTransforms( [ @@ -157,14 +158,14 @@ describe('swc transforms support detection', () => { }); it('updates both privateFieldsAsProperties and setPublicClassFields for private-property-in-object but does not override explicit true', () => { - const base: SwcLoaderOptions = { + const base: SwcConfig = { jsc: { assumptions: { privateFieldsAsProperties: true, setPublicClassFields: true, }, }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig, transformNames } = getSupportedSwcConfigurableTransforms( @@ -200,7 +201,7 @@ describe('swc transforms support detection', () => { const { transformNames } = getSupportedSwcCustomTransforms( transforms, - baseSwcConfig as SwcLoaderOptions + baseSwcConfig as SwcConfig ); expect(transformNames).toEqual([ @@ -214,7 +215,7 @@ describe('swc transforms support detection', () => { }); it('overrides react runtime and importSource from transform-react-jsx config (snapshot)', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: { runtime: 'classic', importSource: 'preact' } }, }, @@ -235,7 +236,7 @@ describe('swc transforms support detection', () => { }); it('should apply default react transform when plugin has no react transform options', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: {} }, }, @@ -252,7 +253,7 @@ describe('swc transforms support detection', () => { }); it('should preserve existing react transform config when plugin has none', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: { runtime: 'automatic', importSource: 'nativewind' }, @@ -271,7 +272,7 @@ describe('swc transforms support detection', () => { }); it('should use plugin importSource option for react transform', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: {}, @@ -295,7 +296,7 @@ describe('swc transforms support detection', () => { }); it('should use plugin importSource option for react transform and override existing importSource', () => { - const inputConfig: SwcLoaderOptions = { + const inputConfig: SwcConfig = { jsc: { transform: { react: { importSource: 'preact' }, @@ -319,7 +320,7 @@ describe('swc transforms support detection', () => { }); it('configures modules commonjs options based on provided config (snapshot)', () => { - const inputConfig: SwcLoaderOptions = {}; + const inputConfig: SwcConfig = {}; const { swcConfig } = getSupportedSwcCustomTransforms( [ [ @@ -333,7 +334,7 @@ describe('swc transforms support detection', () => { }); it('enables external helpers via transform-runtime (snapshot)', () => { - const inputConfig: SwcLoaderOptions = {}; + const inputConfig: SwcConfig = {}; const { swcConfig } = getSupportedSwcCustomTransforms( [['transform-runtime', {}]], inputConfig @@ -342,9 +343,9 @@ describe('swc transforms support detection', () => { }); it('sets exportDefaultFrom only for ecmascript parser; leaves typescript parser unchanged (snapshot)', () => { - const inputConfigTs: SwcLoaderOptions = { + const inputConfigTs: SwcConfig = { jsc: { parser: { syntax: 'typescript' } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig: tsCfg } = getSupportedSwcCustomTransforms( [['proposal-export-default-from', {}]], @@ -352,9 +353,9 @@ describe('swc transforms support detection', () => { ); expect(tsCfg.jsc?.parser).toMatchSnapshot('parser: typescript unchanged'); - const inputConfigEcma: SwcLoaderOptions = { + const inputConfigEcma: SwcConfig = { jsc: { parser: { syntax: 'ecmascript' } }, - } as SwcLoaderOptions; + } as SwcConfig; const { swcConfig: ecmaCfg } = getSupportedSwcCustomTransforms( [['proposal-export-default-from', {}]], inputConfigEcma diff --git a/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts b/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts index 199a9a0ec..22b730d5f 100644 --- a/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts +++ b/packages/repack/src/loaders/babelSwcLoader/babelSwcLoader.ts @@ -1,7 +1,7 @@ import type { TransformOptions } from '@babel/core'; -import type { LoaderContext, SwcLoaderOptions } from '@rspack/core'; +import type { LoaderContext } from '@rspack/core'; import { transform } from '../babelLoader/babelLoader.js'; -import type { BabelSwcLoaderOptions } from './options.js'; +import type { BabelSwcLoaderOptions, SwcConfig } from './options.js'; import { addSwcComplementaryTransforms, getSupportedSwcConfigurableTransforms, @@ -30,7 +30,7 @@ export function partitionTransforms( let configurableTransforms: string[] = []; let customTransforms: string[] = []; - let swcConfig: SwcLoaderOptions = { + let swcConfig: SwcConfig = { jsc: { parser: getSwcParserConfig(filename), transform: { react: { useBuiltins: true } }, @@ -59,7 +59,7 @@ export function partitionTransforms( } export interface BuildFinalSwcConfigOptions { - swcConfig: SwcLoaderOptions; + swcConfig: SwcConfig; includedSwcTransforms: string[]; lazyImports: boolean | string[]; sourceType: 'module' | 'script' | undefined; @@ -67,7 +67,7 @@ export interface BuildFinalSwcConfigOptions { export function buildFinalSwcConfig( options: BuildFinalSwcConfigOptions -): SwcLoaderOptions { +): SwcConfig { const { swcConfig, includedSwcTransforms, lazyImports, sourceType } = options; return { ...swcConfig, @@ -163,8 +163,18 @@ export default async function babelSwcLoader( sourceType: babelResult.sourceType, }); + // `SwcConfig` can carry `builtin:swc-loader`-only options which the raw + // SWC transform API doesn't accept - split them off before calling it + const { + collectTypeScriptInfo: _collectTypeScriptInfo, + transformImport: _transformImport, + rspackExperiments: _rspackExperiments, + detectSyntax: _detectSyntax, + ...transformSwcConfig + } = finalSwcConfig; + const swcResult = swc.transformSync(babelResult?.code!, { - ...finalSwcConfig, + ...transformSwcConfig, caller: { name: '@callstack/repack' }, filename: this.resourcePath, configFile: false, diff --git a/packages/repack/src/loaders/babelSwcLoader/options.ts b/packages/repack/src/loaders/babelSwcLoader/options.ts index 674cf51a8..75668b301 100644 --- a/packages/repack/src/loaders/babelSwcLoader/options.ts +++ b/packages/repack/src/loaders/babelSwcLoader/options.ts @@ -1,9 +1,28 @@ import type { TransformOptions } from '@babel/core'; -import type { SwcLoaderOptions } from '@rspack/core'; +import type { SwcLoaderJscConfig, SwcLoaderOptions } from '@rspack/core'; import type { HermesParserOptions } from '../babelLoader/options.js'; +/** + * Rspack 2 turned `SwcLoaderOptions` into a union discriminated on + * `detectSyntax`, which cannot be spread & reassembled type-safely. + * Re.Pack never sets `detectSyntax`, so internal helpers operate on this + * non-union shape, which stays assignable to `SwcLoaderOptions`. + */ +export type SwcConfig = Omit & { + detectSyntax?: false; + jsc?: SwcLoaderJscConfig; +}; + type BabelOverrides = TransformOptions; -type SwcOverrides = Omit; +// overrides are passed to the raw SWC transform API, so +// `builtin:swc-loader`-only options are not accepted here +type SwcOverrides = Omit< + SwcConfig, + | 'rspackExperiments' + | 'transformImport' + | 'collectTypeScriptInfo' + | 'detectSyntax' +>; export type BabelSwcLoaderOptions = { hideParallelModeWarning?: boolean; diff --git a/packages/repack/src/loaders/babelSwcLoader/swc.ts b/packages/repack/src/loaders/babelSwcLoader/swc.ts index 35ab889ef..e346e1f5f 100644 --- a/packages/repack/src/loaders/babelSwcLoader/swc.ts +++ b/packages/repack/src/loaders/babelSwcLoader/swc.ts @@ -1,4 +1,4 @@ -import type { SwcLoaderOptions } from '@rspack/core'; +import type { SwcConfig } from './options.js'; const SWC_SUPPORTED_NORMAL_RULES = new Set([ 'transform-block-scoping', @@ -80,9 +80,7 @@ export function addSwcComplementaryTransforms( return finalTransforms; } -function getTransformRuntimeConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformRuntimeConfig(swcConfig: SwcConfig): SwcConfig { return { ...swcConfig, jsc: { @@ -92,9 +90,7 @@ function getTransformRuntimeConfig( }; } -function getTransformReactDevelopmentConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformReactDevelopmentConfig(swcConfig: SwcConfig): SwcConfig { return { ...swcConfig, jsc: { @@ -111,9 +107,9 @@ function getTransformReactDevelopmentConfig( } function getTransformReactRuntimeConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, reactRuntimeConfig: Record = {} -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -137,13 +133,13 @@ function getTransformReactRuntimeConfig( } function getTransformModulesCommonjsConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, moduleConfig: Record = { strict: true, strictMode: true, allowTopLevelThis: true, } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, module: { @@ -157,9 +153,7 @@ function getTransformModulesCommonjsConfig( }; } -function getTransformExportDefaultFromConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformExportDefaultFromConfig(swcConfig: SwcConfig): SwcConfig { if (swcConfig.jsc?.parser?.syntax === 'typescript') { return swcConfig; } @@ -176,9 +170,7 @@ function getTransformExportDefaultFromConfig( }; } -function getTransformDynamicImportConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformDynamicImportConfig(swcConfig: SwcConfig): SwcConfig { return { ...swcConfig, jsc: { @@ -193,9 +185,9 @@ function getTransformDynamicImportConfig( } function getTransformClassPropertiesConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -210,9 +202,9 @@ function getTransformClassPropertiesConfig( } function getTransformPrivateMethodsPropertyConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -230,9 +222,9 @@ function getTransformPrivateMethodsPropertyConfig( } function getTransformObjectRestSpreadConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -247,9 +239,9 @@ function getTransformObjectRestSpreadConfig( } function getTransformOptionalChainingNullishCoalescingConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -264,9 +256,9 @@ function getTransformOptionalChainingNullishCoalescingConfig( } function getTransformForOfConfig( - swcConfig: SwcLoaderOptions, + swcConfig: SwcConfig, ruleConfig: Record = { loose: false } -): SwcLoaderOptions { +): SwcConfig { return { ...swcConfig, jsc: { @@ -281,9 +273,7 @@ function getTransformForOfConfig( }; } -function getTransformTypescriptConfig( - swcConfig: SwcLoaderOptions -): SwcLoaderOptions { +function getTransformTypescriptConfig(swcConfig: SwcConfig): SwcConfig { // passthrough return swcConfig; } @@ -322,7 +312,7 @@ export function getSupportedSwcNormalTransforms( export function getSupportedSwcConfigurableTransforms( transforms: [string, Record | undefined][], - swcConfig: SwcLoaderOptions + swcConfig: SwcConfig ) { const transformNames = transforms .filter(([transform]) => SWC_SUPPORTED_CONFIGURABLE_RULES.has(transform)) @@ -341,7 +331,7 @@ export function getSupportedSwcConfigurableTransforms( export function getSupportedSwcCustomTransforms( transforms: [string, Record | undefined][], - swcConfig: SwcLoaderOptions + swcConfig: SwcConfig ) { const transformNames = transforms .filter(([transform]) => SWC_SUPPORTED_CUSTOM_RULES.has(transform)) diff --git a/packages/repack/src/loaders/babelSwcLoader/utils.ts b/packages/repack/src/loaders/babelSwcLoader/utils.ts index 10e19ba26..bde4e504b 100644 --- a/packages/repack/src/loaders/babelSwcLoader/utils.ts +++ b/packages/repack/src/loaders/babelSwcLoader/utils.ts @@ -100,7 +100,13 @@ export function checkParallelModeAvailable( } // in parallel mode compiler.options.experiments are not available // but since we're already running in parallel mode, we can ignore this check - if (loaderContext._compiler.options?.experiments?.parallelLoader) { + // ('in' narrowing: `parallelLoader` no longer exists in Rspack 2 types) + const experiments = loaderContext._compiler.options?.experiments; + if ( + experiments && + 'parallelLoader' in experiments && + experiments.parallelLoader + ) { parallelModeWarningDisplayed = true; logger.warn(disabledParalleModeWarning); } diff --git a/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts b/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts index a06c0b7ad..a2b10f184 100644 --- a/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts +++ b/packages/repack/src/plugins/RepackTargetPlugin/RepackTargetPlugin.ts @@ -117,7 +117,10 @@ export class RepackTargetPlugin { compiler, { chunkId: chunk.id ?? undefined, - hmrEnabled: !!compiler.options.devServer?.hot, + // `devServer` can also be `false` in Rspack 2 types + hmrEnabled: + typeof compiler.options.devServer === 'object' && + !!compiler.options.devServer.hot, } ); diff --git a/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts b/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts index f93c32447..fff3bb307 100644 --- a/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts +++ b/packages/repack/src/plugins/__tests__/HermesBytecodePlugin.test.ts @@ -1,5 +1,6 @@ import fs from 'node:fs'; import os from 'node:os'; +import path from 'node:path'; import { type Compiler, ModuleFilenameHelpers } from '@rspack/core'; import execa from 'execa'; import { HermesBytecodePlugin } from '../HermesBytecodePlugin/index.js'; @@ -108,7 +109,7 @@ describe('HermesBytecodePlugin', () => { expect(execaNodeMock).toHaveBeenCalledTimes(1); expect(execaNodeMock.mock.calls[0][0]).toEqual( - 'path/to/react-native/scripts/compose-source-maps.js' + path.join('path/to/react-native', 'scripts', 'compose-source-maps.js') ); }); @@ -156,7 +157,7 @@ describe('HermesBytecodePlugin', () => { const hermesPath = getHermesCLIPath(reactNativePath); expect(hermesPath).toBe( - 'path/to/hermes-compiler/hermesc/osx-bin/hermesc' + path.join('path/to', 'hermes-compiler', 'hermesc', 'osx-bin', 'hermesc') ); }); @@ -167,7 +168,13 @@ describe('HermesBytecodePlugin', () => { const hermesPath = getHermesCLIPath(reactNativePath); expect(hermesPath).toBe( - 'path/to/react-native/sdks/hermesc/osx-bin/hermesc' + path.join( + 'path/to/react-native', + 'sdks', + 'hermesc', + 'osx-bin', + 'hermesc' + ) ); }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index daa4014d7..0d8fa0cf6 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -664,6 +664,9 @@ importers: '@babel/core': specifier: ^7.29.7 version: 7.29.7 + '@babel/plugin-transform-dynamic-import': + specifier: ^7.24.7 + version: 7.29.7(@babel/core@7.29.7) '@babel/plugin-transform-export-namespace-from': specifier: ^7.29.7 version: 7.29.7(@babel/core@7.29.7) @@ -672,15 +675,18 @@ importers: version: 7.29.7(@babel/core@7.29.7) '@module-federation/enhanced': specifier: 0.8.9 - version: 0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.4) + version: 0.8.9(@rspack/core@2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.4) '@module-federation/sdk': specifier: 0.6.10 version: 0.6.10 '@rspack/core': - specifier: 'catalog:' - version: 1.6.0(@swc/helpers@0.5.23) + specifier: ^2.1.2 + version: 2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23) + '@rspack/core-v1': + specifier: npm:@rspack/core@^1.7.12 + version: '@rspack/core@1.7.12(@swc/helpers@0.5.23)' '@swc/helpers': - specifier: 'catalog:' + specifier: ^0.5.23 version: 0.5.23 '@types/babel__core': specifier: ^7.20.5 @@ -721,6 +727,9 @@ importers: clang-format: specifier: ^1.8.0 version: 1.8.0 + cross-env: + specifier: ^7.0.3 + version: 7.0.3 jest: specifier: ^29.7.0 version: 29.7.0(@types/node@20.19.43) @@ -1809,12 +1818,21 @@ packages: resolution: {integrity: sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==} engines: {node: '>=10.0.0'} + '@emnapi/core@1.11.2': + resolution: {integrity: sha512-TC8MkTuZUtcTSiFeuC0ksCh9QIJ5+F21MvZ4Wn4ORfYaFJ/0dsiudv5tVkejgwZlwQ39jL9WWDe2lz8x0WglOA==} + '@emnapi/core@1.11.3': resolution: {integrity: sha512-zLpS5asjEb7lq8jYLq37N6XKaE41DIexlY1rF/z4/tIl3wo13Sqm28fRyfIsKZD+NZ8mM5RoKkpW/rBcuoSZSg==} + '@emnapi/runtime@1.11.2': + resolution: {integrity: sha512-kyOl3X0DuTiT1h2ft8r2fYO8JYtU9a9Xis/zBSiGArNaagCOWx90N1k2wxp18czFDH+OgcWGb5ZP/XMt3dcyPA==} + '@emnapi/runtime@1.11.3': resolution: {integrity: sha512-Xz4Tpyki7XyrpbUK1jR1AhdAdaXyhhY4lZ3neLodmhpuWfy2PAQN5B46sAiU4liOXGLkHypn/qU+jvfWSCYYLA==} + '@emnapi/wasi-threads@1.2.2': + resolution: {integrity: sha512-c95qOXkHdydNKhscBTebqEC1CVAZpyqOfVfBzQ1qgzyl3gfeldUjIggDbIZgDKsHLgnsM+igH7TJ/eAasaVuMA==} + '@emnapi/wasi-threads@1.2.3': resolution: {integrity: sha512-ELEBe8PsLvvJ6QMr0zLt8ffvOHW/dc1m3CEzNMg7aJUv3bMaoDtw2TXyDAwkYBuroxxuHEwhRTLJSe5sya547g==} @@ -2758,6 +2776,9 @@ packages: '@module-federation/error-codes@0.21.2': resolution: {integrity: sha512-mGbPAAApgjmQUl4J7WAt20aV04a26TyS21GDEpOGXFEQG5FqmZnSJ6FqB8K19HgTKioBT1+fF/Ctl5bGGao/EA==} + '@module-federation/error-codes@0.22.0': + resolution: {integrity: sha512-xF9SjnEy7vTdx+xekjPCV5cIHOGCkdn3pIxo9vU7gEZMIw0SvAEdsy6Uh17xaCpm8V0FWvR0SZoK9Ik6jGOaug==} + '@module-federation/error-codes@0.8.9': resolution: {integrity: sha512-yUA3GZjOy8Ll6l193faXir2veexDaUiLdmptbzC9tIee/iSQiSwIlibdTafCfqaJ62cLZaytOUdmAFAKLv8QQw==} @@ -2894,6 +2915,9 @@ packages: '@module-federation/runtime-core@0.21.2': resolution: {integrity: sha512-LtDnccPxjR8Xqa3daRYr1cH/6vUzK3mQSzgvnfsUm1fXte5syX4ftWw3Eu55VdqNY3yREFRn77AXdu9PfPEZRw==} + '@module-federation/runtime-core@0.22.0': + resolution: {integrity: sha512-GR1TcD6/s7zqItfhC87zAp30PqzvceoeDGYTgF3Vx2TXvsfDrhP6Qw9T4vudDQL3uJRne6t7CzdT29YyVxlgIA==} + '@module-federation/runtime-core@0.6.17': resolution: {integrity: sha512-PXFN/TT9f64Un6NQYqH1Z0QLhpytW15jkZvTEOV8W7Ed319BECFI0Rv4xAsAGa8zJGFoaM/c7QOQfdFXtKj5Og==} @@ -2915,6 +2939,9 @@ packages: '@module-federation/runtime-tools@0.21.2': resolution: {integrity: sha512-SgG9NWTYGNYcHSd5MepO3AXf6DNXriIo4sKKM4mu4RqfYhHyP+yNjnF/gvYJl52VD61g0nADmzLWzBqxOqk2tg==} + '@module-federation/runtime-tools@0.22.0': + resolution: {integrity: sha512-4ScUJ/aUfEernb+4PbLdhM/c60VHl698Gn1gY21m9vyC1Ucn69fPCA1y2EwcCB7IItseRMoNhdcWQnzt/OPCNA==} + '@module-federation/runtime-tools@0.8.9': resolution: {integrity: sha512-xBUGx1oOZNuxXjPGdTMrLtAIDrbrN6jE2Mgb9w1qr2mQ4AW9b5TOlxbARBoX4q98xt9oFCGU6Q0eW5XJpsl8AQ==} @@ -2936,6 +2963,9 @@ packages: '@module-federation/runtime@0.21.2': resolution: {integrity: sha512-97jlOx4RAnAHMBTfgU5FBK6+V/pfT6GNX0YjSf8G+uJ3lFy74Y6kg/BevEkChTGw5waCLAkw/pw4LmntYcNN7g==} + '@module-federation/runtime@0.22.0': + resolution: {integrity: sha512-38g5iPju2tPC3KHMPxRKmy4k4onNp6ypFPS1eKGsNLUkXgHsPMBFqAjDw96iEcjri91BrahG4XcdyKi97xZzlA==} + '@module-federation/runtime@0.8.9': resolution: {integrity: sha512-i+a+/hoT/c+EE52mT+gJrbA6DhL86PY9cd/dIv/oKpLz9i+yYBlG+RA+puc7YsUEO4irbFLvnIMq6AGDUKVzYA==} @@ -2957,6 +2987,9 @@ packages: '@module-federation/sdk@0.21.2': resolution: {integrity: sha512-t2vHSJ1a9zjg7LLJoEghcytNLzeFCqOat5TbXTav5dgU0xXw82Cf0EfLrxiJL6uUpgbtyvUdqqa2DVAvMPjiiA==} + '@module-federation/sdk@0.22.0': + resolution: {integrity: sha512-x4aFNBKn2KVQRuNVC5A7SnrSCSqyfIWmm1DvubjbO9iKFe7ith5niw8dqSFBekYBg2Fwy+eMg4sEFNVvCAdo6g==} + '@module-federation/sdk@0.6.10': resolution: {integrity: sha512-i6ofHnImB4zCn/bt7Ft0zh9o/PxvsJj8Wc88EAeJg4IrY6+bzwwo1G2h44w1Yt3go4skZZFQCK0UxoaV6l/t/A==} @@ -2996,6 +3029,9 @@ packages: '@module-federation/webpack-bundler-runtime@0.21.2': resolution: {integrity: sha512-06R/NDY6Uh5RBIaBOFwYWzJCf1dIiQd/DFHToBVhejUT3ZFG7GzHEPIIsAGqMzne/JSmVsvjlXiJu7UthQ6rFA==} + '@module-federation/webpack-bundler-runtime@0.22.0': + resolution: {integrity: sha512-aM8gCqXu+/4wBmJtVeMeeMN5guw3chf+2i6HajKtQv7SJfxV/f4IyNQJUeUQu9HfiAZHjqtMV5Lvq/Lvh8LdyA==} + '@module-federation/webpack-bundler-runtime@0.8.9': resolution: {integrity: sha512-DYLvVi4b2MUYu/B4g5wIC5SHxiODboKHkYGHYapOhCcqOchca/N16gtiAI8eSNjJPc+fgUXUGIyGiB18IlFEeQ==} @@ -3008,6 +3044,12 @@ packages: '@napi-rs/wasm-runtime@1.0.7': resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3': resolution: {integrity: sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==} @@ -3488,11 +3530,21 @@ packages: cpu: [arm64] os: [darwin] + '@rspack/binding-darwin-arm64@1.7.12': + resolution: {integrity: sha512-rbFprJaJiqrmfy8SHth8EsoRS0wg4bXcucwj9NiMzpGFq14Opw8c04iQ6H9BECYzgmN0PKZ9rh41LdVvhdZe4A==} + cpu: [arm64] + os: [darwin] + '@rspack/binding-darwin-arm64@2.0.0-alpha.1': resolution: {integrity: sha512-+6E6pYgpKvs41cyOlqRjpCT3djjL9hnntF61JumM/TNo1aTYXMNNG4b8ZsLMpBq5ZwCy9Dg8oEDe8AZ84rfM7A==} cpu: [arm64] os: [darwin] + '@rspack/binding-darwin-arm64@2.1.5': + resolution: {integrity: sha512-XLAN6YSU36qkciJtV9DY9z57pdHOjKy/f1HyoqpZenRg8p46jnXPziV45lfrTZpG+FF6g/jtTUc4dKbeyoWqPw==} + cpu: [arm64] + os: [darwin] + '@rspack/binding-darwin-x64@1.3.9': resolution: {integrity: sha512-rYuOUINhnhLDbG5LHHKurRSuKIsw0LKUHcd6AAsFmijo4RMnGBJ4NOI4tOLAQvkoSTQ+HU5wiTGSQOgHVhYreQ==} cpu: [x64] @@ -3503,11 +3555,21 @@ packages: cpu: [x64] 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.0-alpha.1': resolution: {integrity: sha512-Ccf9NNupVe67vlaS9zKQJ+BvsAn385uBC1vXnYaUxxHoY/tEwNJf6t+XyDARt7mCtT7+Bu4L/iJ/JEF/MsO5zg==} cpu: [x64] os: [darwin] + '@rspack/binding-darwin-x64@2.1.5': + resolution: {integrity: sha512-KLW7PV86jyCOyqJSqrkZdvYUWYCFX/Q4LsGmVc8tyDA8jBYLMHJDewC/lNf9ot3rU2SoLDZKhDUh7q7dX0FRmg==} + cpu: [x64] + os: [darwin] + '@rspack/binding-linux-arm64-gnu@1.3.9': resolution: {integrity: sha512-pBKnS2Fbn9cDtWe1KcD1qRjQlJwQhP9pFW2KpxdjE7qXbaO11IHtem6dLZwdpNqbDn9QgyfdVGXBDvBaP1tGwA==} cpu: [arm64] @@ -3520,12 +3582,24 @@ packages: os: [linux] libc: [glibc] + '@rspack/binding-linux-arm64-gnu@1.7.12': + resolution: {integrity: sha512-C8owWG+yvo7X0oVLIXetkoJhIFBP1LYNcAQqtgLmJnQLQDklGuP83dKC+zISGQWpjawHfZ1ER96vLgoTrxKZdw==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-arm64-gnu@2.0.0-alpha.1': resolution: {integrity: sha512-B7omNsPSsinOq2VRD4d4VFrLgHceMQobqlLg0txFUZ7PDjE307gpTcGViWQlUhNCbkZXMPzDeXBFa5ZlEmxgnA==} cpu: [arm64] os: [linux] libc: [glibc] + '@rspack/binding-linux-arm64-gnu@2.1.5': + resolution: {integrity: sha512-KOooAC8L+Ljx5sY7ZuMeaXCQ310FNWaPWXcYQJpFPApF3qyLeSfuOftUGwxcxeo5U0mS5OY3zxp7/5CaHWKYjg==} + cpu: [arm64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-arm64-musl@1.3.9': resolution: {integrity: sha512-0B+iiINW0qOEkBE9exsRcdmcHtYIWAoJGnXrz9tUiiewRxX0Cmm0MjD2HAVUAggJZo+9IN8RGz5PopCjJ/dn1g==} cpu: [arm64] @@ -3538,12 +3612,36 @@ packages: os: [linux] libc: [musl] + '@rspack/binding-linux-arm64-musl@1.7.12': + resolution: {integrity: sha512-i51WWI64aRpsfSki6rN0aepPqXkVfS+vZM7+4bWDcmnhUmdMvhIPcYg0QRk3DtyJnu33jqNLM0WHY78k00NyfA==} + cpu: [arm64] + os: [linux] + libc: [musl] + '@rspack/binding-linux-arm64-musl@2.0.0-alpha.1': resolution: {integrity: sha512-NCG401ofZcDKlTWD8VHv76Y+02Stmd9Nu5MRbVUBOCTVgXMj8Mgrm5XsGBWUjzd5J/Mvo2hstCKIZxNzmPd8uQ==} cpu: [arm64] os: [linux] libc: [musl] + '@rspack/binding-linux-arm64-musl@2.1.5': + resolution: {integrity: sha512-0GFc07gT71+uRbHtejDecBfSL0fs7dQAwCtXYieXboACauL7UvS3Hwr6v8A91aGtAcvLotnCaIa3CWWYwtYlYQ==} + cpu: [arm64] + os: [linux] + libc: [musl] + + '@rspack/binding-linux-riscv64-gnu@2.1.5': + resolution: {integrity: sha512-isQQDp3fBzPSZpLVFzPqVXIVA4I9b9mKs58TfUgOzDP/1g1582YSV3iFopgFogvEliihXDuuXvM6aAkP+w8Z+Q==} + cpu: [riscv64] + os: [linux] + libc: [glibc] + + '@rspack/binding-linux-riscv64-musl@2.1.5': + resolution: {integrity: sha512-/SP6VknY4kH60BYplI2FDNAJCo4U4DUszLxhKsgVlgA5ImgHC8Ew2AsKgidk7ceiYV9OcKzYuWYe9tVpysBYVA==} + cpu: [riscv64] + os: [linux] + libc: [musl] + '@rspack/binding-linux-x64-gnu@1.3.9': resolution: {integrity: sha512-82izGJw/qxJ4xaHJy/A4MF7aTRT9tE6VlWoWM4rJmqRszfujN/w54xJRie9jkt041TPvJWGNpYD4Hjpt0/n/oA==} cpu: [x64] @@ -3556,12 +3654,24 @@ packages: os: [linux] libc: [glibc] + '@rspack/binding-linux-x64-gnu@1.7.12': + resolution: {integrity: sha512-MSos0FuPEefqo9V92ULd5hggKG29EkSNg1zDcypy0OkpsKh5pfjVxTLYFXgTcVyFoUQQbdG8zFBzYbwmJ8V4ew==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-x64-gnu@2.0.0-alpha.1': resolution: {integrity: sha512-Xgp8wJ5gjpPG8I3VMEsVAesfckWryQVUhJkHcxPfNi72QTv8UkMER7Jl+JrlQk7K7nMO5ltokx/VGl1c3tMx+w==} cpu: [x64] os: [linux] libc: [glibc] + '@rspack/binding-linux-x64-gnu@2.1.5': + resolution: {integrity: sha512-/GJmS+buA4pilT10gs5mfAhAZxSHXpDD8veZ3QpYvNUuoU9gvempAq9TgjbyNN/vc5pf76GdXPXKFMiehudYSA==} + cpu: [x64] + os: [linux] + libc: [glibc] + '@rspack/binding-linux-x64-musl@1.3.9': resolution: {integrity: sha512-V9nDg63iPI6Z7kM11UPV5kBdOdLXPIu3IgI2ObON5Rd4KEZr7RLo/Q4HKzj0IH27Zwl5qeBJdx69zZdu66eOqg==} cpu: [x64] @@ -3574,20 +3684,40 @@ packages: os: [linux] libc: [musl] + '@rspack/binding-linux-x64-musl@1.7.12': + resolution: {integrity: sha512-JcAMVKXOnjfpC3coWjCFPWD3Yl8RBw6a+IXQQ8mfRlHaHMIiOv8IfZqx15XRxMUn49CtP7Z0Na8iiAg2aKrcfw==} + cpu: [x64] + os: [linux] + libc: [musl] + '@rspack/binding-linux-x64-musl@2.0.0-alpha.1': resolution: {integrity: sha512-lrYKcOgsPA1UMswxzFAV37ofkznbtTLCcEas6lxtlT3Dr28P6VRzC8TgVbIiprkm10I0BlThQWDJ3aGzzLj9Kg==} cpu: [x64] os: [linux] libc: [musl] + '@rspack/binding-linux-x64-musl@2.1.5': + resolution: {integrity: sha512-iwS3t75nZ2TnUjB05KtvpvjpdkOy/nLxbaOnwjbdnNZZXpUaMadLbllGAWayHPGCMsL2yKBEhVEESZpR7tK3SA==} + cpu: [x64] + os: [linux] + libc: [musl] + '@rspack/binding-wasm32-wasi@1.6.0': resolution: {integrity: sha512-XGwX35XXnoTYVUGwDBsKNOkkk/yUsT/RF59u9BwT3QBM5eSXk767xVw/ZeiiyJf5YfI/52HDW2E4QZyvlYyv7g==} cpu: [wasm32] + '@rspack/binding-wasm32-wasi@1.7.12': + resolution: {integrity: sha512-n+ZqP6ZMc0nhOgvadg5VhEs9ojtbES80AcWeFnmGkbzIszvGSO63GKNiRkXtjJ9KFuRzytbbmsCqkUVH+Tywxg==} + cpu: [wasm32] + '@rspack/binding-wasm32-wasi@2.0.0-alpha.1': resolution: {integrity: sha512-rppGiT7CtXlM8st+IgzBDqb7V//1xx5Oe0SY1sxxw0cfOGMpIQCwhJqx/uI6ioqJLZLGX/obt359+hPXyqGl4w==} cpu: [wasm32] + '@rspack/binding-wasm32-wasi@2.1.5': + resolution: {integrity: sha512-jOhW69t1H/jcRaSMB5U8jVzWP18j0YQIlo0nT8W+KvNVScJeyOze4FFc+5RIS7VmuT8/jid7hUyydZOfm6UgqA==} + cpu: [wasm32] + '@rspack/binding-win32-arm64-msvc@1.3.9': resolution: {integrity: sha512-owWCJTezFkiBOSRzH+eOTN15H5QYyThHE5crZ0I30UmpoSEchcPSCvddliA0W62ZJIOgG4IUSNamKBiiTwdjLQ==} cpu: [arm64] @@ -3598,11 +3728,21 @@ packages: cpu: [arm64] os: [win32] + '@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.0-alpha.1': resolution: {integrity: sha512-yD2g1JmnCxrix/344r7lBn+RH+Nv8uWP0UDP8kwv4kQGCWr4U7IP8PKFpoyulVOgOUjvJpgImeyrDJ7R8he+5w==} cpu: [arm64] os: [win32] + '@rspack/binding-win32-arm64-msvc@2.1.5': + resolution: {integrity: sha512-OLfMXmtFBcrWr9BRGKXJYrWgYR0JSaoAWr3EVFDjKGi/YR5aUwQSGc3AJPBph9g0YsdSqRuUhtQGtCk84DeeEA==} + cpu: [arm64] + os: [win32] + '@rspack/binding-win32-ia32-msvc@1.3.9': resolution: {integrity: sha512-YUuNA8lkGSXJ07fOjkX+yuWrWcsU5x5uGFuAYsglw+rDTWCS6m9HSwQjbCp7HUp81qPszjSk+Ore5XVh07FKeQ==} cpu: [ia32] @@ -3613,11 +3753,21 @@ packages: cpu: [ia32] os: [win32] + '@rspack/binding-win32-ia32-msvc@1.7.12': + resolution: {integrity: sha512-cDMGwTRSa2p9fNBVe1wTRkF2AEXZ9ARWW36QeC5CkLaI0Ezz8lvhF2+CSOPnhaQ1O1qtn0L0SF+lFnrY+I7xGQ==} + cpu: [ia32] + os: [win32] + '@rspack/binding-win32-ia32-msvc@2.0.0-alpha.1': resolution: {integrity: sha512-5qpQL5Qz3uYb56pwffEGzznXSX9TNkLpigQbIObfnUwX7WkdjgTT7oTHpjn2sRSLLNiJ/jCp2r4ZHvjmnNRsRA==} cpu: [ia32] os: [win32] + '@rspack/binding-win32-ia32-msvc@2.1.5': + resolution: {integrity: sha512-p4OSmnj21+AY8vpIADveLEBXfXJRXonOTYim2VLVWV4TbXfhYNMLiX3qESHCdNnn6lVJM0q6zxxzEUfTyAKydw==} + cpu: [ia32] + os: [win32] + '@rspack/binding-win32-x64-msvc@1.3.9': resolution: {integrity: sha512-E0gtYBVt5vRj0zBeplEf8wsVDPDQ6XBdRiFVUgmgwYUYYkXaalaIvbD1ioB8cA05vfz8HrPGXcMrgletUP4ojA==} cpu: [x64] @@ -3628,20 +3778,36 @@ packages: cpu: [x64] 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.0-alpha.1': resolution: {integrity: sha512-dZ76NN9tXLaF2gnB/pU+PcK4Adf9tj8dY06KcWk5F81ur2V4UbrMfkWJkQprur8cgL/F49YtFMRWa4yp/qNbpQ==} cpu: [x64] os: [win32] + '@rspack/binding-win32-x64-msvc@2.1.5': + resolution: {integrity: sha512-YCkLLDGMkHsw5CpcsFtFhzCu+JZEsNrcH9O1GpWMkyxR2ku2Fq1i2wEHYSm26HyW+PJ3+Fv347MPWMFZIz9q2g==} + cpu: [x64] + os: [win32] + '@rspack/binding@1.3.9': resolution: {integrity: sha512-3FFen1/0F2aP5uuCm8vPaJOrzM3karCPNMsc5gLCGfEy2rsK38Qinf9W4p1bw7+FhjOTzoSdkX+LFHeMDVxJhw==} '@rspack/binding@1.6.0': resolution: {integrity: sha512-RqlCjvWg/LkJjHpsbI48ebo2SYpIBJsV1eh9SEMfXo1batAPvB5grhAbLX0MRUOtzuQOnZMCDGdr2v7l2L8Siw==} + '@rspack/binding@1.7.12': + resolution: {integrity: sha512-f4HHuLbvuld8Ba4iB/4ibse5XrKxFrgmM3S4P2AOKnPlekAFlBjmltCuaTL/W2ggYvILaVY+YcFXrEH1rrKeQA==} + '@rspack/binding@2.0.0-alpha.1': resolution: {integrity: sha512-Glz0SNFYPtNVM+ExJ4ocSzW+oQhb1iHTmxqVEAILbL17Hq3N/nwZpo1cWEs6hJjn8cosJIb1VKbbgb/1goEtCQ==} + '@rspack/binding@2.1.5': + resolution: {integrity: sha512-lF3ZLeeyV0AN3BL0m2jAmNZD5pP9IHsQ8gUXN7mo0g4xsW6nf6hsN7o9CnEHECz5uUZb+EoWsuWzAAmnA9Ip8Q==} + '@rspack/core@1.3.9': resolution: {integrity: sha512-u7usd9srCBPBfNJCSvsfh14AOPq6LCVna0Vb/aA2nyJTawHqzfAMz1QRb/e27nP3NrV6RPiwx03W494Dd6r6wg==} engines: {node: '>=16.0.0'} @@ -3660,6 +3826,15 @@ packages: '@swc/helpers': optional: true + '@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.0-alpha.1': resolution: {integrity: sha512-2KK3hbxrRqzxtzg+ka7LsiEKIWIGIQz317k9HHC2U4IC5yLJ31K8y/vQfA1aIT2QcFls9gW7GyRjp8A4X5cvLA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -3672,6 +3847,18 @@ packages: '@swc/helpers': optional: true + '@rspack/core@2.1.5': + resolution: {integrity: sha512-YHjL7xVXycAWsjJtF39cRZ2u+ddiNFxY+FcNgEBe6Y8OaLeUfMfjba3gK+B1Oj32UcKD6BmXGsPfu9p+OII/Yw==} + 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.0.1': resolution: {integrity: sha512-VynGOEsVw2s8TAlLf/uESfrgfrq2+rcXB1muPJYBWbsm1Oa6r5qVQhjA5ggM6z/coYPrsVMgovl3Ff7Q7OCp1w==} engines: {node: '>=16.0.0'} @@ -4896,6 +5083,11 @@ packages: resolution: {integrity: sha512-p0SaNjrHOnQeR8/VnfGbmg9te2kfyYSQ7Sc/j/6DtPL3JQvKxmjO9TSjNFpujqV3vEYYBvNNvXSxzyksBWAx1Q==} engines: {node: '>=12.0.0'} + cross-env@7.0.3: + resolution: {integrity: sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==} + engines: {node: '>=10.14', npm: '>=6', yarn: '>=1'} + hasBin: true + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -9897,17 +10089,33 @@ snapshots: '@discoveryjs/json-ext@0.5.7': {} + '@emnapi/core@1.11.2': + dependencies: + '@emnapi/wasi-threads': 1.2.2 + tslib: 2.8.1 + optional: true + '@emnapi/core@1.11.3': dependencies: '@emnapi/wasi-threads': 1.2.3 tslib: 2.8.1 optional: true + '@emnapi/runtime@1.11.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.11.3': dependencies: tslib: 2.8.1 optional: true + '@emnapi/wasi-threads@1.2.2': + dependencies: + tslib: 2.8.1 + optional: true + '@emnapi/wasi-threads@1.2.3': dependencies: tslib: 2.8.1 @@ -10907,7 +11115,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/enhanced@0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.4)': + '@module-federation/enhanced@0.8.9(@rspack/core@2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23))(react-dom@19.2.8(react@19.2.3))(react@19.2.3)(typescript@5.9.3)(webpack@5.105.4)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.8.9 '@module-federation/data-prefetch': 0.8.9(react-dom@19.2.8(react@19.2.3))(react@19.2.3) @@ -10916,7 +11124,7 @@ snapshots: '@module-federation/inject-external-runtime-core-plugin': 0.8.9(@module-federation/runtime-tools@0.8.9) '@module-federation/managers': 0.8.9 '@module-federation/manifest': 0.8.9(typescript@5.9.3) - '@module-federation/rspack': 0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3) + '@module-federation/rspack': 0.8.9(@rspack/core@2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23))(typescript@5.9.3) '@module-federation/runtime-tools': 0.8.9 '@module-federation/sdk': 0.8.9 btoa: 1.2.1 @@ -10992,6 +11200,8 @@ snapshots: '@module-federation/error-codes@0.21.2': {} + '@module-federation/error-codes@0.22.0': {} + '@module-federation/error-codes@0.8.9': {} '@module-federation/error-codes@2.0.1': {} @@ -11155,7 +11365,7 @@ snapshots: - supports-color - utf-8-validate - '@module-federation/rspack@0.8.9(@rspack/core@1.6.0(@swc/helpers@0.5.23))(typescript@5.9.3)': + '@module-federation/rspack@0.8.9(@rspack/core@2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23))(typescript@5.9.3)': dependencies: '@module-federation/bridge-react-webpack-plugin': 0.8.9 '@module-federation/dts-plugin': 0.8.9(typescript@5.9.3) @@ -11164,7 +11374,7 @@ snapshots: '@module-federation/manifest': 0.8.9(typescript@5.9.3) '@module-federation/runtime-tools': 0.8.9 '@module-federation/sdk': 0.8.9 - '@rspack/core': 1.6.0(@swc/helpers@0.5.23) + '@rspack/core': 2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23) optionalDependencies: typescript: 5.9.3 transitivePeerDependencies: @@ -11228,6 +11438,11 @@ snapshots: '@module-federation/error-codes': 0.21.2 '@module-federation/sdk': 0.21.2 + '@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@0.6.17': dependencies: '@module-federation/error-codes': 0.8.9 @@ -11263,6 +11478,11 @@ snapshots: '@module-federation/runtime': 0.21.2 '@module-federation/webpack-bundler-runtime': 0.21.2 + '@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@0.8.9': dependencies: '@module-federation/runtime': 0.8.9 @@ -11302,6 +11522,12 @@ snapshots: '@module-federation/runtime-core': 0.21.2 '@module-federation/sdk': 0.21.2 + '@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@0.8.9': dependencies: '@module-federation/error-codes': 0.8.9 @@ -11328,6 +11554,8 @@ snapshots: '@module-federation/sdk@0.21.2': {} + '@module-federation/sdk@0.22.0': {} + '@module-federation/sdk@0.6.10': {} '@module-federation/sdk@0.8.9': @@ -11384,6 +11612,11 @@ snapshots: '@module-federation/runtime': 0.21.2 '@module-federation/sdk': 0.21.2 + '@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@0.8.9': dependencies: '@module-federation/runtime': 0.8.9 @@ -11407,6 +11640,13 @@ snapshots: '@tybys/wasm-util': 0.10.3 optional: true + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2)': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@tybys/wasm-util': 0.10.3 + optional: true + '@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3': optional: true @@ -12128,91 +12368,163 @@ snapshots: '@rspack/binding-darwin-arm64@1.6.0': optional: true + '@rspack/binding-darwin-arm64@1.7.12': + optional: true + '@rspack/binding-darwin-arm64@2.0.0-alpha.1': optional: true + '@rspack/binding-darwin-arm64@2.1.5': + optional: true + '@rspack/binding-darwin-x64@1.3.9': optional: true '@rspack/binding-darwin-x64@1.6.0': optional: true + '@rspack/binding-darwin-x64@1.7.12': + optional: true + '@rspack/binding-darwin-x64@2.0.0-alpha.1': optional: true + '@rspack/binding-darwin-x64@2.1.5': + optional: true + '@rspack/binding-linux-arm64-gnu@1.3.9': optional: true '@rspack/binding-linux-arm64-gnu@1.6.0': optional: true + '@rspack/binding-linux-arm64-gnu@1.7.12': + optional: true + '@rspack/binding-linux-arm64-gnu@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-arm64-gnu@2.1.5': + optional: true + '@rspack/binding-linux-arm64-musl@1.3.9': optional: true '@rspack/binding-linux-arm64-musl@1.6.0': optional: true + '@rspack/binding-linux-arm64-musl@1.7.12': + optional: true + '@rspack/binding-linux-arm64-musl@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-arm64-musl@2.1.5': + optional: true + + '@rspack/binding-linux-riscv64-gnu@2.1.5': + optional: true + + '@rspack/binding-linux-riscv64-musl@2.1.5': + optional: true + '@rspack/binding-linux-x64-gnu@1.3.9': optional: true '@rspack/binding-linux-x64-gnu@1.6.0': optional: true + '@rspack/binding-linux-x64-gnu@1.7.12': + optional: true + '@rspack/binding-linux-x64-gnu@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-x64-gnu@2.1.5': + optional: true + '@rspack/binding-linux-x64-musl@1.3.9': optional: true '@rspack/binding-linux-x64-musl@1.6.0': optional: true + '@rspack/binding-linux-x64-musl@1.7.12': + optional: true + '@rspack/binding-linux-x64-musl@2.0.0-alpha.1': optional: true + '@rspack/binding-linux-x64-musl@2.1.5': + optional: true + '@rspack/binding-wasm32-wasi@1.6.0': dependencies: '@napi-rs/wasm-runtime': 1.0.7 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.0-alpha.1': dependencies: '@napi-rs/wasm-runtime': 1.0.7 optional: true + '@rspack/binding-wasm32-wasi@2.1.5': + dependencies: + '@emnapi/core': 1.11.2 + '@emnapi/runtime': 1.11.2 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.11.2)(@emnapi/runtime@1.11.2) + optional: true + '@rspack/binding-win32-arm64-msvc@1.3.9': optional: true '@rspack/binding-win32-arm64-msvc@1.6.0': optional: true + '@rspack/binding-win32-arm64-msvc@1.7.12': + optional: true + '@rspack/binding-win32-arm64-msvc@2.0.0-alpha.1': optional: true + '@rspack/binding-win32-arm64-msvc@2.1.5': + optional: true + '@rspack/binding-win32-ia32-msvc@1.3.9': optional: true '@rspack/binding-win32-ia32-msvc@1.6.0': optional: true + '@rspack/binding-win32-ia32-msvc@1.7.12': + optional: true + '@rspack/binding-win32-ia32-msvc@2.0.0-alpha.1': optional: true + '@rspack/binding-win32-ia32-msvc@2.1.5': + optional: true + '@rspack/binding-win32-x64-msvc@1.3.9': optional: true '@rspack/binding-win32-x64-msvc@1.6.0': optional: true + '@rspack/binding-win32-x64-msvc@1.7.12': + optional: true + '@rspack/binding-win32-x64-msvc@2.0.0-alpha.1': optional: true + '@rspack/binding-win32-x64-msvc@2.1.5': + optional: true + '@rspack/binding@1.3.9': optionalDependencies: '@rspack/binding-darwin-arm64': 1.3.9 @@ -12238,6 +12550,19 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 1.6.0 '@rspack/binding-win32-x64-msvc': 1.6.0 + '@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.0-alpha.1': optionalDependencies: '@rspack/binding-darwin-arm64': 2.0.0-alpha.1 @@ -12251,6 +12576,21 @@ snapshots: '@rspack/binding-win32-ia32-msvc': 2.0.0-alpha.1 '@rspack/binding-win32-x64-msvc': 2.0.0-alpha.1 + '@rspack/binding@2.1.5': + optionalDependencies: + '@rspack/binding-darwin-arm64': 2.1.5 + '@rspack/binding-darwin-x64': 2.1.5 + '@rspack/binding-linux-arm64-gnu': 2.1.5 + '@rspack/binding-linux-arm64-musl': 2.1.5 + '@rspack/binding-linux-riscv64-gnu': 2.1.5 + '@rspack/binding-linux-riscv64-musl': 2.1.5 + '@rspack/binding-linux-x64-gnu': 2.1.5 + '@rspack/binding-linux-x64-musl': 2.1.5 + '@rspack/binding-wasm32-wasi': 2.1.5 + '@rspack/binding-win32-arm64-msvc': 2.1.5 + '@rspack/binding-win32-ia32-msvc': 2.1.5 + '@rspack/binding-win32-x64-msvc': 2.1.5 + '@rspack/core@1.3.9(@swc/helpers@0.5.23)': dependencies: '@module-federation/runtime-tools': 0.13.1 @@ -12268,6 +12608,14 @@ snapshots: optionalDependencies: '@swc/helpers': 0.5.23 + '@rspack/core@1.7.12(@swc/helpers@0.5.23)': + dependencies: + '@module-federation/runtime-tools': 0.22.0 + '@rspack/binding': 1.7.12 + '@rspack/lite-tapable': 1.1.0 + optionalDependencies: + '@swc/helpers': 0.5.23 + '@rspack/core@2.0.0-alpha.1(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23)': dependencies: '@rspack/binding': 2.0.0-alpha.1 @@ -12276,6 +12624,13 @@ snapshots: '@module-federation/runtime-tools': 2.8.0 '@swc/helpers': 0.5.23 + '@rspack/core@2.1.5(@module-federation/runtime-tools@2.8.0)(@swc/helpers@0.5.23)': + dependencies: + '@rspack/binding': 2.1.5 + optionalDependencies: + '@module-federation/runtime-tools': 2.8.0 + '@swc/helpers': 0.5.23 + '@rspack/lite-tapable@1.0.1': {} '@rspack/lite-tapable@1.1.0': {} @@ -13597,6 +13952,10 @@ snapshots: dependencies: luxon: 3.7.2 + cross-env@7.0.3: + dependencies: + cross-spawn: 7.0.6 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 diff --git a/turbo.json b/turbo.json index 2ea4ab76f..29b69d2c2 100644 --- a/turbo.json +++ b/turbo.json @@ -9,6 +9,10 @@ "dependsOn": ["^build"] }, "test": { + "dependsOn": ["^build"], + "env": ["RSPACK_MAJOR"] + }, + "test:rspack1": { "dependsOn": ["^build"] }, "pods": {