shakapacker 9.6.0 → 9.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/docs/releasing.md CHANGED
@@ -47,26 +47,29 @@ The simplest way to release is with no arguments — the task reads the version
47
47
 
48
48
  ```bash
49
49
  # Recommended: reads version from CHANGELOG.md (requires step 1)
50
- bundle exec rake create_release
50
+ bundle exec rake release
51
51
 
52
52
  # For a specific version (overrides CHANGELOG.md detection)
53
- bundle exec rake "create_release[9.1.0]"
53
+ bundle exec rake "release[9.1.0]"
54
54
 
55
55
  # For a beta release (note: use period, not dash)
56
- bundle exec rake "create_release[9.2.0.beta.1]" # Creates npm package 9.2.0-beta.1
56
+ bundle exec rake "release[9.2.0.beta.1]" # Creates npm package 9.2.0-beta.1
57
57
 
58
58
  # For a release candidate
59
- bundle exec rake "create_release[9.6.0.rc.0]"
59
+ bundle exec rake "release[9.6.0.rc.0]"
60
60
 
61
61
  # Dry run to test without publishing
62
- bundle exec rake "create_release[9.1.0,true]"
62
+ bundle exec rake "release[9.1.0,true]"
63
+
64
+ # Skip interactive confirmations (for scripted maintainer runs)
65
+ AUTO_CONFIRM=true bundle exec rake release
63
66
 
64
67
  # Override version policy checks (monotonic + changelog/bump consistency)
65
- RELEASE_VERSION_POLICY_OVERRIDE=true bundle exec rake "create_release[9.1.0]"
66
- bundle exec rake "create_release[9.1.0,false,true]"
68
+ RELEASE_VERSION_POLICY_OVERRIDE=true bundle exec rake "release[9.1.0]"
69
+ bundle exec rake "release[9.1.0,false,true]"
67
70
  ```
68
71
 
69
- When called with no arguments, `create_release`:
72
+ When called with no arguments, `release`:
70
73
 
71
74
  1. Reads the first versioned header from CHANGELOG.md (e.g., `## [v9.6.0]`)
72
75
  2. Compares it to the current gem version
@@ -74,8 +77,9 @@ When called with no arguments, `create_release`:
74
77
  4. If no new version is found, falls back to a patch bump
75
78
 
76
79
  Dry runs use a temporary git worktree so version bumps and installs do not modify your current checkout.
80
+ Dry runs now also print explicit "skipping confirmation" messages and the would-run GitHub release command.
77
81
 
78
- `create_release` validates release-version policy before publishing:
82
+ `release` validates release-version policy before publishing:
79
83
 
80
84
  - Target version must be greater than the latest tagged release.
81
85
  - If the versioned target changelog section exists (`## [vX.Y.Z...]`; not `UNRELEASED`), it maps to expected bump type:
@@ -87,11 +91,11 @@ Dry runs use a temporary git worktree so version bumps and installs do not modif
87
91
  Use override only when needed:
88
92
 
89
93
  - `RELEASE_VERSION_POLICY_OVERRIDE=true`
90
- - Or task arg override (`create_release[..., ..., true]`)
94
+ - Or task arg override (`release[..., ..., true]`)
91
95
 
92
96
  ### 3. What the Release Task Does
93
97
 
94
- The `create_release` task automatically:
98
+ The `release` task automatically:
95
99
 
96
100
  1. **Validates release prerequisites**:
97
101
  - Verifies npm authentication
@@ -108,7 +112,8 @@ The `create_release` task automatically:
108
112
  - Prompts for RubyGems OTP (2FA code)
109
113
  6. **Updates spec/dummy lockfiles:**
110
114
  - Runs `bundle install` to update `Gemfile.lock`
111
- - Runs `npm install` to update `package-lock.json` (yarn.lock may also be updated for multi-package-manager compatibility testing)
115
+ - Runs `yarn install` to refresh the Yarn-managed dummy app lockfile
116
+ - Runs `npm install` to keep `package-lock.json` in sync for npm compatibility/testing
112
117
  7. **Commits and pushes lockfile changes** automatically
113
118
  8. **Creates GitHub release** from CHANGELOG.md (if the matching section exists)
114
119
 
@@ -133,24 +138,26 @@ The task automatically converts Ruby gem format to npm semver format:
133
138
 
134
139
  ```bash
135
140
  # Regular release
136
- bundle exec rake "create_release[9.1.0]" # Gem: 9.1.0, npm: 9.1.0
141
+ bundle exec rake "release[9.1.0]" # Gem: 9.1.0, npm: 9.1.0
137
142
 
138
143
  # Beta release
139
- bundle exec rake "create_release[9.2.0.beta.1]" # Gem: 9.2.0.beta.1, npm: 9.2.0-beta.1
144
+ bundle exec rake "release[9.2.0.beta.1]" # Gem: 9.2.0.beta.1, npm: 9.2.0-beta.1
140
145
 
141
146
  # Release candidate
142
- bundle exec rake "create_release[10.0.0.rc.1]" # Gem: 10.0.0.rc.1, npm: 10.0.0-rc.1
147
+ bundle exec rake "release[10.0.0.rc.1]" # Gem: 10.0.0.rc.1, npm: 10.0.0-rc.1
143
148
 
144
- # Prerelease: use /update-changelog rc first, then create_release reads it
145
- bundle exec rake create_release # reads v10.0.0-rc.0 from CHANGELOG.md
149
+ # Prerelease: use /update-changelog rc first, then release reads it
150
+ bundle exec rake release # reads v10.0.0-rc.0 from CHANGELOG.md
146
151
  ```
147
152
 
148
153
  ### 5. During the Release
149
154
 
155
+ If you are running non-interactively, set `AUTO_CONFIRM=true` to skip confirmation prompts.
156
+
150
157
  1. When prompted for **npm OTP**, enter your 2FA code from your authenticator app
151
158
  2. Accept defaults for release-it options
152
159
  3. When prompted for **RubyGems OTP**, enter your 2FA code
153
- 4. If using `create_release` with no version, confirm the version detected from CHANGELOG.md (or the computed patch version)
160
+ 4. If using `release` with no version, confirm the version detected from CHANGELOG.md (or the computed patch version)
154
161
  5. The script will automatically commit and push lockfile updates
155
162
  6. The script will automatically create a GitHub release (if CHANGELOG.md section exists)
156
163
 
data/docs/rspack.md CHANGED
@@ -4,9 +4,33 @@ Shakapacker supports [Rspack](https://rspack.rs) as an alternative assets bundle
4
4
 
5
5
  **📖 For configuration options, see the [Configuration Guide](./configuration.md)**
6
6
 
7
+ ## Version Compatibility
8
+
9
+ Shakapacker supports both Rspack v1 (`^1.0.0`) and Rspack v2 (`^2.0.0-0`). No configuration changes are needed when upgrading between rspack versions — shakapacker's generated config works with both.
10
+
11
+ **Rspack v2 note:** Rspack v2 ships as a pure ESM package and requires **Node.js 20.19.0+**.
12
+
13
+ **Rspack v1 note:** Rspack v1 itself supports older Node versions, but Shakapacker requires Node 20+.
14
+
15
+ **React refresh plugin note:** `@rspack/plugin-react-refresh` currently remains on the v1 line in Shakapacker peer deps.
16
+
17
+ **Current CI coverage note:** Shakapacker currently validates rspack v2 using `2.0.0-beta.6`. The rspack v2 dev dependencies are intentionally pinned while v2 is in beta and should be revisited when stable `2.0.0` is released.
18
+
19
+ ### Why upgrade to Rspack v2?
20
+
21
+ - **Persistent cache with proper invalidation** — Rspack v2 promotes persistent caching (`cache.type: 'filesystem'`) from experimental to stable, with portable cache support (`cache.portable`) and read-only cache for CI (`cache.readonly`). This means fast rebuilds that survive process restarts and are properly invalidated when dependencies change.
22
+ - **Incremental compilation (stable)** — The `incremental` option moves from `experiments` to a top-level config, signaling it's production-ready. Incremental builds skip unchanged work in the dependency graph.
23
+ - **Better tree shaking** — CJS `require()` destructuring and variable property access are now tree-shaken, and Module Federation shares can be tree-shaken.
24
+ - **Unified target configuration** — A single `target` setting now propagates defaults to SWC and LightningCSS automatically, eliminating redundant per-loader configuration.
25
+ - **Stricter export validation** — `exportsPresence` defaults to `'error'`, catching missing or misspelled exports at build time instead of silently producing broken bundles.
26
+ - **React Server Components** — Built-in RSC support for frameworks.
27
+ - **Performance** — Dozens of Rust-level optimizations across every beta release (hash caching, regex fast paths, reduced allocations, rayon parallelism).
28
+
29
+ See the [Rspack v2 breaking changes discussion](https://github.com/web-infra-dev/rspack/discussions/9270) for full details.
30
+
7
31
  ## Installation
8
32
 
9
- First, install the required Rspack dependencies:
33
+ Install the required Rspack dependencies:
10
34
 
11
35
  ```bash
12
36
  npm install @rspack/core @rspack/cli -D
@@ -13,16 +13,30 @@ class Shakapacker::Env
13
13
 
14
14
  def inquire
15
15
  fallback_env_warning if config_path.exist? && !current
16
- current || FALLBACK_ENV.inquiry
16
+ (current || FALLBACK_ENV).inquiry
17
17
  end
18
18
 
19
19
  private
20
20
  def current
21
- Rails.env.presence_in(available_environments)
21
+ env = if defined?(Rails) && Rails.respond_to?(:env)
22
+ Rails.env
23
+ else
24
+ ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || Shakapacker::DEFAULT_ENV
25
+ end
26
+ env.presence_in(available_environments)
22
27
  end
23
28
 
24
29
  def fallback_env_warning
25
- logger.info "RAILS_ENV=#{Rails.env} environment is not defined in #{config_path}, falling back to #{FALLBACK_ENV} environment"
30
+ env_value = if defined?(Rails) && Rails.respond_to?(:env)
31
+ Rails.env
32
+ else
33
+ ENV["RAILS_ENV"].presence || ENV["RACK_ENV"].presence || Shakapacker::DEFAULT_ENV
34
+ end
35
+ logger.info "RAILS_ENV=#{env_value} environment is not defined in #{config_path}, falling back to #{FALLBACK_ENV} environment"
36
+ rescue NameError, NoMethodError
37
+ # Logger may not be fully functional without Rails (e.g., ActiveSupport::IsolatedExecutionState
38
+ # is not available). Fall back to puts, matching Configuration#log_fallback.
39
+ puts "RAILS_ENV=#{env_value} environment is not defined in #{config_path}, falling back to #{FALLBACK_ENV} environment"
26
40
  end
27
41
 
28
42
  def available_environments
@@ -296,7 +296,8 @@ module Shakapacker
296
296
  if child_pid
297
297
  Process.kill("TERM", child_pid)
298
298
  else
299
- raise SignalException, "TERM" # if there is no child_pid we never spawned the process and can quit as normal
299
+ # Signal arrived before spawn completed; re-raise so the process exits normally.
300
+ raise SignalException, "TERM"
300
301
  end
301
302
  rescue Errno::ESRCH
302
303
  nil
@@ -1,4 +1,4 @@
1
1
  module Shakapacker
2
2
  # Change the version in package.json too, please!
3
- VERSION = "9.6.0".freeze
3
+ VERSION = "9.7.0".freeze
4
4
  end
@@ -712,6 +712,17 @@ async function runAllBuildsCommand(options: ExportOptions): Promise<number> {
712
712
  // Apply defaults
713
713
  const resolvedOptions = applyDefaults(options)
714
714
 
715
+ // Validate paths for security in all-builds mode.
716
+ // saveDir is always set by applyDefaults(); --output is not used in --all-builds mode.
717
+ safeResolvePath(appRoot, resolvedOptions.saveDir!)
718
+
719
+ // Keep in sync with validation in run()
720
+ if (resolvedOptions.annotate && resolvedOptions.format !== "yaml") {
721
+ throw new Error(
722
+ "Annotation requires YAML format. Use --no-annotate or --format=yaml."
723
+ )
724
+ }
725
+
715
726
  const loader = new ConfigFileLoader(resolvedOptions.configFile)
716
727
  if (!loader.exists()) {
717
728
  const configPath = resolvedOptions.configFile || DEFAULT_CONFIG_FILE
@@ -58,9 +58,14 @@ const getPlugins = (): unknown[] => {
58
58
  config.integrity?.enabled &&
59
59
  moduleExists("webpack-subresource-integrity")
60
60
  ) {
61
- const SubresourceIntegrityPlugin = requireOrError(
61
+ // webpack-subresource-integrity v5+ exports the plugin as a named export.
62
+ const subresourceIntegrityModule = requireOrError(
62
63
  "webpack-subresource-integrity"
63
64
  )
65
+ const SubresourceIntegrityPlugin =
66
+ "SubresourceIntegrityPlugin" in subresourceIntegrityModule
67
+ ? subresourceIntegrityModule.SubresourceIntegrityPlugin
68
+ : subresourceIntegrityModule
64
69
  plugins.push(
65
70
  new SubresourceIntegrityPlugin({
66
71
  hashFuncNames: config.integrity.hash_functions,
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "shakapacker",
3
- "version": "9.6.0",
3
+ "version": "9.7.0",
4
4
  "description": "Use webpack to manage app-like JavaScript modules in Rails",
5
5
  "homepage": "https://github.com/shakacode/shakapacker",
6
6
  "bugs": {
@@ -51,8 +51,8 @@
51
51
  "devDependencies": {
52
52
  "@eslint/eslintrc": "^3.2.0",
53
53
  "@eslint/js": "^9.37.0",
54
- "@rspack/cli": "^1.5.8",
55
- "@rspack/core": "^1.5.8",
54
+ "@rspack/cli": "2.0.0-beta.6",
55
+ "@rspack/core": "2.0.0-beta.6",
56
56
  "@swc/core": "^1.3.0",
57
57
  "@types/babel__core": "^7.20.5",
58
58
  "@types/js-yaml": "^4.0.9",
@@ -99,8 +99,8 @@
99
99
  "@babel/plugin-transform-runtime": "^7.17.0",
100
100
  "@babel/preset-env": "^7.16.11",
101
101
  "@babel/runtime": "^7.17.9",
102
- "@rspack/cli": "^1.0.0",
103
- "@rspack/core": "^1.0.0",
102
+ "@rspack/cli": "^1.0.0 || ^2.0.0-0",
103
+ "@rspack/core": "^1.0.0 || ^2.0.0-0",
104
104
  "@rspack/plugin-react-refresh": "^1.0.0",
105
105
  "@swc/core": "^1.3.0",
106
106
  "@types/babel__core": "^7.0.0",
@@ -5,6 +5,43 @@
5
5
  * then re-require bundlerUtils to exercise the rspack branches.
6
6
  */
7
7
 
8
+ // Mock requireOrError to provide a fake @rspack/core (v2 is pure ESM, can't be require()'d by Jest)
9
+ jest.mock("../../package/utils/requireOrError", () => {
10
+ const CssExtractRspackPlugin = jest.fn(function (options) {
11
+ this.options = options
12
+ })
13
+ CssExtractRspackPlugin.loader = "css-extract-rspack-loader"
14
+
15
+ return {
16
+ requireOrError: (moduleName) => {
17
+ if (moduleName === "@rspack/core") {
18
+ return {
19
+ DefinePlugin: jest.fn(function (definitions) {
20
+ this.definitions = definitions
21
+ }),
22
+ EnvironmentPlugin: jest.fn(function (env) {
23
+ this.env = env
24
+ }),
25
+ ProvidePlugin: jest.fn(function (definitions) {
26
+ this.definitions = definitions
27
+ }),
28
+ HotModuleReplacementPlugin: jest.fn(),
29
+ ProgressPlugin: jest.fn(),
30
+ CssExtractRspackPlugin,
31
+ SubresourceIntegrityPlugin: jest.fn(function (options) {
32
+ this.options = options
33
+ }),
34
+ SwcJsMinimizerRspackPlugin: jest.fn(),
35
+ LightningCssMinimizerRspackPlugin: jest.fn()
36
+ }
37
+ }
38
+ return jest
39
+ .requireActual("../../package/utils/requireOrError")
40
+ .requireOrError(moduleName)
41
+ }
42
+ }
43
+ })
44
+
8
45
  let bundlerUtils
9
46
 
10
47
  describe("bundlerUtils with rspack", () => {
@@ -80,7 +117,9 @@ describe("bundlerUtils with rspack", () => {
80
117
  test("returns rspack DefinePlugin", () => {
81
118
  const DefinePlugin = bundlerUtils.getDefinePlugin()
82
119
  expect(DefinePlugin).toBeDefined()
83
- expect(DefinePlugin).toBeInstanceOf(Function)
120
+
121
+ const instance = new DefinePlugin({ FOO: "bar" })
122
+ expect(instance.definitions).toStrictEqual({ FOO: "bar" })
84
123
  })
85
124
  })
86
125
 
@@ -88,7 +127,9 @@ describe("bundlerUtils with rspack", () => {
88
127
  test("returns rspack EnvironmentPlugin", () => {
89
128
  const EnvironmentPlugin = bundlerUtils.getEnvironmentPlugin()
90
129
  expect(EnvironmentPlugin).toBeDefined()
91
- expect(EnvironmentPlugin).toBeInstanceOf(Function)
130
+
131
+ const instance = new EnvironmentPlugin(["NODE_ENV"])
132
+ expect(instance.env).toStrictEqual(["NODE_ENV"])
92
133
  })
93
134
  })
94
135
 
@@ -96,7 +137,9 @@ describe("bundlerUtils with rspack", () => {
96
137
  test("returns rspack ProvidePlugin", () => {
97
138
  const ProvidePlugin = bundlerUtils.getProvidePlugin()
98
139
  expect(ProvidePlugin).toBeDefined()
99
- expect(ProvidePlugin).toBeInstanceOf(Function)
140
+
141
+ const instance = new ProvidePlugin({ React: "react" })
142
+ expect(instance.definitions).toStrictEqual({ React: "react" })
100
143
  })
101
144
  })
102
145
  })
@@ -455,5 +455,37 @@ describe("configExporter", () => {
455
455
  parseArguments(["--all-builds", "--save-dir=./configs"])
456
456
  }).not.toThrow()
457
457
  })
458
+
459
+ test("run rejects --all-builds with annotate and non-yaml format", async () => {
460
+ const { run } = require("../../package/configExporter/cli")
461
+ const mockConsoleError = jest
462
+ .spyOn(console, "error")
463
+ .mockImplementation(() => {})
464
+
465
+ const result = await run(["--all-builds", "--annotate", "--format=json"])
466
+
467
+ expect(result).toBe(1)
468
+ expect(mockConsoleError).toHaveBeenCalledWith(
469
+ expect.stringContaining("Annotation requires YAML format")
470
+ )
471
+
472
+ mockConsoleError.mockRestore()
473
+ })
474
+
475
+ test("run validates --all-builds save-dir path traversal", async () => {
476
+ const { run } = require("../../package/configExporter/cli")
477
+ const mockConsoleError = jest
478
+ .spyOn(console, "error")
479
+ .mockImplementation(() => {})
480
+
481
+ const result = await run(["--all-builds", "--save-dir=../outside"])
482
+
483
+ expect(result).toBe(1)
484
+ expect(mockConsoleError).toHaveBeenCalledWith(
485
+ expect.stringContaining("[SHAKAPACKER SECURITY] Path traversal attempt")
486
+ )
487
+
488
+ mockConsoleError.mockRestore()
489
+ })
458
490
  })
459
491
  })
@@ -0,0 +1,89 @@
1
+ const loadPluginsWithSriModule = (sriModule) => {
2
+ let getPlugins
3
+
4
+ jest.isolateModules(() => {
5
+ jest.doMock("../../../package/config", () => ({
6
+ manifestPath: "public/packs/manifest.json",
7
+ publicPathWithoutCDN: "/packs/",
8
+ integrity: {
9
+ enabled: true,
10
+ hash_functions: ["sha256"]
11
+ },
12
+ css_extract_ignore_order_warnings: false,
13
+ useContentHash: false
14
+ }))
15
+
16
+ jest.doMock("../../../package/env", () => ({
17
+ isProduction: true
18
+ }))
19
+
20
+ jest.doMock("../../../package/utils/helpers", () => ({
21
+ moduleExists: (moduleName) =>
22
+ moduleName === "webpack-subresource-integrity"
23
+ }))
24
+
25
+ jest.doMock("../../../package/utils/ensureManifestExists", () => ({
26
+ __esModule: true,
27
+ default: jest.fn()
28
+ }))
29
+
30
+ jest.doMock("../../../package/utils/requireOrError", () => ({
31
+ requireOrError: (moduleName) => {
32
+ if (moduleName === "webpack-assets-manifest") {
33
+ return function WebpackAssetsManifest() {}
34
+ }
35
+ if (moduleName === "webpack") {
36
+ return {
37
+ EnvironmentPlugin: function EnvironmentPlugin() {}
38
+ }
39
+ }
40
+ if (moduleName === "webpack-subresource-integrity") {
41
+ return sriModule
42
+ }
43
+
44
+ throw new Error(`Unexpected module request: ${moduleName}`)
45
+ }
46
+ }))
47
+ ;({ getPlugins } = require("../../../package/plugins/webpack"))
48
+ })
49
+
50
+ return getPlugins
51
+ }
52
+
53
+ describe("webpack plugins - webpack-subresource-integrity compatibility", () => {
54
+ afterEach(() => {
55
+ jest.clearAllMocks()
56
+ })
57
+
58
+ test("supports webpack-subresource-integrity v5 named export", () => {
59
+ const SubresourceIntegrityPlugin = jest.fn(
60
+ function SubresourceIntegrityPluginMock(options) {
61
+ this.options = options
62
+ }
63
+ )
64
+ const getPlugins = loadPluginsWithSriModule({ SubresourceIntegrityPlugin })
65
+
66
+ getPlugins()
67
+
68
+ expect(SubresourceIntegrityPlugin).toHaveBeenCalledWith({
69
+ hashFuncNames: ["sha256"],
70
+ enabled: true
71
+ })
72
+ })
73
+
74
+ test("supports webpack-subresource-integrity default export", () => {
75
+ const SubresourceIntegrityPlugin = jest.fn(
76
+ function SubresourceIntegrityPluginMock(options) {
77
+ this.options = options
78
+ }
79
+ )
80
+ const getPlugins = loadPluginsWithSriModule(SubresourceIntegrityPlugin)
81
+
82
+ getPlugins()
83
+
84
+ expect(SubresourceIntegrityPlugin).toHaveBeenCalledWith({
85
+ hashFuncNames: ["sha256"],
86
+ enabled: true
87
+ })
88
+ })
89
+ })
@@ -1,4 +1,4 @@
1
- /* eslint-disable jest/no-conditional-in-test */
1
+ /* eslint-disable func-names, jest/no-conditional-in-test */
2
2
 
3
3
  const { chdirTestApp } = require("../../helpers")
4
4
 
@@ -29,6 +29,48 @@ jest.mock("../../../package/utils/validateDependencies", () => ({
29
29
  validateRspackDependencies: jest.fn()
30
30
  }))
31
31
 
32
+ // Mock requireOrError to provide a fake @rspack/core (v2 is pure ESM, can't be require()'d by Jest)
33
+ jest.mock("../../../package/utils/requireOrError", () => ({
34
+ requireOrError: (moduleName) => {
35
+ if (moduleName === "@rspack/core") {
36
+ const CssExtractRspackPlugin = jest.fn(function (options) {
37
+ this.options = options
38
+ })
39
+ CssExtractRspackPlugin.loader = "css-extract-rspack-loader"
40
+
41
+ return {
42
+ DefinePlugin: jest.fn(function (definitions) {
43
+ this.definitions = definitions
44
+ }),
45
+ EnvironmentPlugin: jest.fn(function (env) {
46
+ this.env = env
47
+ }),
48
+ ProvidePlugin: jest.fn(function (definitions) {
49
+ this.definitions = definitions
50
+ }),
51
+ HotModuleReplacementPlugin: jest.fn(),
52
+ ProgressPlugin: jest.fn(),
53
+ CssExtractRspackPlugin,
54
+ SubresourceIntegrityPlugin: jest.fn(function (options) {
55
+ this.options = options
56
+ }),
57
+ SwcJsMinimizerRspackPlugin: jest.fn(),
58
+ LightningCssMinimizerRspackPlugin: jest.fn()
59
+ }
60
+ }
61
+ if (moduleName === "rspack-manifest-plugin") {
62
+ return {
63
+ RspackManifestPlugin: jest.fn(function (options) {
64
+ this.options = options
65
+ })
66
+ }
67
+ }
68
+ return jest
69
+ .requireActual("../../../package/utils/requireOrError")
70
+ .requireOrError(moduleName)
71
+ }
72
+ }))
73
+
32
74
  describe("rspack/index", () => {
33
75
  let rspackIndex
34
76
  let validateRspackDependencies