shakapacker 8.0.2 → 9.2.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.
Files changed (198) hide show
  1. checksums.yaml +4 -4
  2. data/.eslintignore +1 -0
  3. data/.eslintrc.fast.js +40 -0
  4. data/.eslintrc.js +48 -0
  5. data/.github/STATUS.md +1 -0
  6. data/.github/workflows/claude-code-review.yml +54 -0
  7. data/.github/workflows/claude.yml +50 -0
  8. data/.github/workflows/dummy.yml +9 -4
  9. data/.github/workflows/generator.yml +32 -10
  10. data/.github/workflows/node.yml +23 -1
  11. data/.github/workflows/ruby.yml +33 -2
  12. data/.github/workflows/test-bundlers.yml +170 -0
  13. data/.gitignore +20 -0
  14. data/.husky/pre-commit +2 -0
  15. data/.npmignore +56 -0
  16. data/.prettierignore +3 -0
  17. data/.rubocop.yml +1 -0
  18. data/.yalcignore +26 -0
  19. data/CHANGELOG.md +302 -16
  20. data/CLAUDE.md +29 -0
  21. data/CONTRIBUTING.md +138 -20
  22. data/Gemfile.lock +83 -89
  23. data/README.md +343 -105
  24. data/Rakefile +39 -4
  25. data/TODO.md +50 -0
  26. data/TODO_v9.md +87 -0
  27. data/bin/export-bundler-config +11 -0
  28. data/conductor-setup.sh +70 -0
  29. data/conductor.json +7 -0
  30. data/docs/cdn_setup.md +379 -0
  31. data/docs/common-upgrades.md +615 -0
  32. data/docs/css-modules-export-mode.md +512 -0
  33. data/docs/deployment.md +62 -9
  34. data/docs/optional-peer-dependencies.md +198 -0
  35. data/docs/peer-dependencies.md +60 -0
  36. data/docs/react.md +6 -14
  37. data/docs/releasing.md +197 -0
  38. data/docs/rspack.md +190 -0
  39. data/docs/rspack_migration_guide.md +305 -0
  40. data/docs/subresource_integrity.md +54 -0
  41. data/docs/transpiler-migration.md +209 -0
  42. data/docs/transpiler-performance.md +179 -0
  43. data/docs/troubleshooting.md +157 -22
  44. data/docs/typescript-migration.md +379 -0
  45. data/docs/typescript.md +99 -0
  46. data/docs/using_esbuild_loader.md +3 -3
  47. data/docs/using_swc_loader.md +112 -10
  48. data/docs/v6_upgrade.md +10 -0
  49. data/docs/v8_upgrade.md +3 -5
  50. data/docs/v9_upgrade.md +458 -0
  51. data/gemfiles/Gemfile-rails.6.0.x +2 -1
  52. data/gemfiles/Gemfile-rails.6.1.x +1 -1
  53. data/gemfiles/Gemfile-rails.7.0.x +2 -2
  54. data/gemfiles/Gemfile-rails.7.1.x +1 -2
  55. data/gemfiles/Gemfile-rails.7.2.x +11 -0
  56. data/gemfiles/Gemfile-rails.8.0.x +11 -0
  57. data/lib/install/bin/export-bundler-config +11 -0
  58. data/lib/install/bin/shakapacker +4 -6
  59. data/lib/install/bin/shakapacker-dev-server +1 -1
  60. data/lib/install/config/rspack/rspack.config.js +6 -0
  61. data/lib/install/config/rspack/rspack.config.ts +7 -0
  62. data/lib/install/config/shakapacker.yml +25 -5
  63. data/lib/install/config/webpack/webpack.config.ts +7 -0
  64. data/lib/install/package.json +38 -0
  65. data/lib/install/template.rb +194 -44
  66. data/lib/shakapacker/bundler_switcher.rb +329 -0
  67. data/lib/shakapacker/compiler.rb +2 -1
  68. data/lib/shakapacker/compiler_strategy.rb +2 -2
  69. data/lib/shakapacker/configuration.rb +173 -2
  70. data/lib/shakapacker/dev_server_runner.rb +29 -8
  71. data/lib/shakapacker/digest_strategy.rb +2 -1
  72. data/lib/shakapacker/doctor.rb +905 -0
  73. data/lib/shakapacker/helper.rb +64 -16
  74. data/lib/shakapacker/manifest.rb +10 -3
  75. data/lib/shakapacker/mtime_strategy.rb +1 -1
  76. data/lib/shakapacker/railtie.rb +4 -4
  77. data/lib/shakapacker/rspack_runner.rb +19 -0
  78. data/lib/shakapacker/runner.rb +159 -10
  79. data/lib/shakapacker/swc_migrator.rb +384 -0
  80. data/lib/shakapacker/utils/manager.rb +15 -2
  81. data/lib/shakapacker/version.rb +1 -1
  82. data/lib/shakapacker/version_checker.rb +2 -2
  83. data/lib/shakapacker/webpack_runner.rb +6 -43
  84. data/lib/shakapacker.rb +22 -11
  85. data/lib/tasks/shakapacker/doctor.rake +8 -0
  86. data/lib/tasks/shakapacker/export_bundler_config.rake +72 -0
  87. data/lib/tasks/shakapacker/install.rake +12 -2
  88. data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
  89. data/lib/tasks/shakapacker/switch_bundler.rake +82 -0
  90. data/lib/tasks/shakapacker.rake +2 -0
  91. data/package/.npmignore +4 -0
  92. data/package/babel/preset.ts +56 -0
  93. data/package/config.ts +175 -0
  94. data/package/configExporter/cli.ts +683 -0
  95. data/package/configExporter/configDocs.ts +102 -0
  96. data/package/configExporter/fileWriter.ts +92 -0
  97. data/package/configExporter/index.ts +5 -0
  98. data/package/configExporter/types.ts +36 -0
  99. data/package/configExporter/yamlSerializer.ts +266 -0
  100. data/package/{dev_server.js → dev_server.ts} +8 -5
  101. data/package/env.ts +92 -0
  102. data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +30 -0
  103. data/package/environments/{base.js → base.ts} +56 -60
  104. data/package/environments/development.ts +90 -0
  105. data/package/environments/production.ts +80 -0
  106. data/package/environments/test.ts +53 -0
  107. data/package/environments/types.ts +98 -0
  108. data/package/esbuild/index.ts +42 -0
  109. data/package/index.d.ts +3 -60
  110. data/package/index.ts +55 -0
  111. data/package/loaders.d.ts +28 -0
  112. data/package/optimization/rspack.ts +36 -0
  113. data/package/optimization/webpack.ts +57 -0
  114. data/package/plugins/rspack.ts +103 -0
  115. data/package/plugins/webpack.ts +62 -0
  116. data/package/rspack/index.ts +64 -0
  117. data/package/rules/{babel.js → babel.ts} +2 -2
  118. data/package/rules/{coffee.js → coffee.ts} +1 -1
  119. data/package/rules/css.ts +3 -0
  120. data/package/rules/{erb.js → erb.ts} +1 -1
  121. data/package/rules/esbuild.ts +10 -0
  122. data/package/rules/file.ts +40 -0
  123. data/package/rules/{jscommon.js → jscommon.ts} +4 -4
  124. data/package/rules/{less.js → less.ts} +4 -4
  125. data/package/rules/raw.ts +25 -0
  126. data/package/rules/rspack.ts +176 -0
  127. data/package/rules/{sass.js → sass.ts} +7 -3
  128. data/package/rules/{stylus.js → stylus.ts} +4 -8
  129. data/package/rules/swc.ts +10 -0
  130. data/package/rules/webpack.ts +16 -0
  131. data/package/swc/index.ts +56 -0
  132. data/package/types/README.md +88 -0
  133. data/package/types/index.ts +61 -0
  134. data/package/types.ts +108 -0
  135. data/package/utils/configPath.ts +6 -0
  136. data/package/utils/debug.ts +49 -0
  137. data/package/utils/defaultConfigPath.ts +4 -0
  138. data/package/utils/errorCodes.ts +219 -0
  139. data/package/utils/errorHelpers.ts +143 -0
  140. data/package/utils/getStyleRule.ts +64 -0
  141. data/package/utils/helpers.ts +85 -0
  142. data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
  143. data/package/utils/pathValidation.ts +139 -0
  144. data/package/utils/requireOrError.ts +15 -0
  145. data/package/utils/snakeToCamelCase.ts +5 -0
  146. data/package/utils/typeGuards.ts +342 -0
  147. data/package/utils/validateDependencies.ts +61 -0
  148. data/package/webpack-types.d.ts +33 -0
  149. data/package/webpackDevServerConfig.ts +117 -0
  150. data/package-lock.json +13047 -0
  151. data/package.json +154 -18
  152. data/scripts/remove-use-strict.js +45 -0
  153. data/scripts/type-check-no-emit.js +27 -0
  154. data/test/helpers.js +1 -1
  155. data/test/package/config.test.js +43 -0
  156. data/test/package/env.test.js +42 -7
  157. data/test/package/environments/base.test.js +5 -1
  158. data/test/package/rules/babel.test.js +16 -0
  159. data/test/package/rules/esbuild.test.js +1 -1
  160. data/test/package/rules/raw.test.js +40 -7
  161. data/test/package/rules/swc.test.js +1 -1
  162. data/test/package/rules/webpack.test.js +35 -0
  163. data/test/package/staging.test.js +4 -3
  164. data/test/package/transpiler-defaults.test.js +127 -0
  165. data/test/peer-dependencies.sh +85 -0
  166. data/test/scripts/remove-use-strict.test.js +125 -0
  167. data/test/typescript/build.test.js +118 -0
  168. data/test/typescript/environments.test.js +107 -0
  169. data/test/typescript/pathValidation.test.js +142 -0
  170. data/test/typescript/securityValidation.test.js +182 -0
  171. data/tools/README.md +124 -0
  172. data/tools/css-modules-v9-codemod.js +179 -0
  173. data/tsconfig.eslint.json +16 -0
  174. data/tsconfig.json +38 -0
  175. data/yarn.lock +4165 -2706
  176. metadata +129 -41
  177. data/package/babel/preset.js +0 -37
  178. data/package/config.js +0 -54
  179. data/package/env.js +0 -48
  180. data/package/environments/development.js +0 -13
  181. data/package/environments/production.js +0 -88
  182. data/package/environments/test.js +0 -3
  183. data/package/esbuild/index.js +0 -40
  184. data/package/index.js +0 -40
  185. data/package/rules/css.js +0 -3
  186. data/package/rules/esbuild.js +0 -10
  187. data/package/rules/file.js +0 -29
  188. data/package/rules/index.js +0 -20
  189. data/package/rules/raw.js +0 -5
  190. data/package/rules/swc.js +0 -10
  191. data/package/swc/index.js +0 -50
  192. data/package/utils/configPath.js +0 -4
  193. data/package/utils/defaultConfigPath.js +0 -2
  194. data/package/utils/getStyleRule.js +0 -40
  195. data/package/utils/helpers.js +0 -58
  196. data/package/utils/snakeToCamelCase.js +0 -5
  197. data/package/webpackDevServerConfig.js +0 -71
  198. data/test/package/rules/index.test.js +0 -16
@@ -0,0 +1,176 @@
1
+ /* eslint global-require: 0 */
2
+
3
+ const { moduleExists } = require("../utils/helpers")
4
+ const { debug, info, warn } = require("../utils/debug")
5
+
6
+ debug("Loading Rspack rules configuration...")
7
+
8
+ const rules = []
9
+
10
+ // Use Rspack's built-in SWC loader for JavaScript files
11
+ debug("Adding JavaScript rule with builtin:swc-loader")
12
+ rules.push({
13
+ test: /\.(js|jsx|mjs)$/,
14
+ exclude: /node_modules/,
15
+ // The 'type' field is required for Rspack to properly handle JavaScript modules
16
+ // when using builtin loaders. It ensures correct module parsing and transformation.
17
+ type: "javascript/auto",
18
+ use: [
19
+ {
20
+ loader: "builtin:swc-loader",
21
+ options: {
22
+ jsc: {
23
+ parser: {
24
+ syntax: "ecmascript",
25
+ jsx: true
26
+ },
27
+ transform: {
28
+ react: {
29
+ runtime: "automatic"
30
+ }
31
+ }
32
+ }
33
+ }
34
+ }
35
+ ]
36
+ })
37
+
38
+ // Use Rspack's built-in SWC loader for TypeScript files
39
+ debug("Adding TypeScript rule with builtin:swc-loader")
40
+ rules.push({
41
+ test: /\.(ts|tsx)$/,
42
+ exclude: /node_modules/,
43
+ // The 'type' field is required for Rspack to properly handle TypeScript modules
44
+ // when using builtin loaders. It ensures correct module parsing and transformation.
45
+ type: "javascript/auto",
46
+ use: [
47
+ {
48
+ loader: "builtin:swc-loader",
49
+ options: {
50
+ jsc: {
51
+ parser: {
52
+ syntax: "typescript",
53
+ tsx: true
54
+ },
55
+ transform: {
56
+ react: {
57
+ runtime: "automatic"
58
+ }
59
+ }
60
+ }
61
+ }
62
+ }
63
+ ]
64
+ })
65
+
66
+ // CSS rules using Rspack's built-in CSS handling
67
+ debug("Checking for CSS loader...")
68
+ if (moduleExists("css-loader")) {
69
+ debug("css-loader found, loading CSS rule configuration...")
70
+ const css = require("./css")
71
+ if (css) {
72
+ debug("Successfully added CSS rule")
73
+ rules.push(css)
74
+ } else {
75
+ warn("css-loader found but rule configuration returned null")
76
+ }
77
+ } else {
78
+ info("Skipping CSS support - css-loader not installed")
79
+ }
80
+
81
+ // Sass rules
82
+ debug("Checking for Sass loader...")
83
+ if (moduleExists("sass") && moduleExists("sass-loader")) {
84
+ debug("sass and sass-loader found, loading Sass rule configuration...")
85
+ const sass = require("./sass")
86
+ if (sass) {
87
+ debug("Successfully added Sass rule")
88
+ rules.push(sass)
89
+ } else {
90
+ warn("sass and sass-loader found but rule configuration returned null")
91
+ }
92
+ } else if (!moduleExists("sass")) {
93
+ info("Skipping Sass support - sass not installed")
94
+ } else if (!moduleExists("sass-loader")) {
95
+ info("Skipping Sass support - sass-loader not installed")
96
+ }
97
+
98
+ // Less rules
99
+ debug("Checking for Less loader...")
100
+ if (moduleExists("less") && moduleExists("less-loader")) {
101
+ debug("less and less-loader found, loading Less rule configuration...")
102
+ const less = require("./less")
103
+ if (less) {
104
+ debug("Successfully added Less rule")
105
+ rules.push(less)
106
+ } else {
107
+ warn("less and less-loader found but rule configuration returned null")
108
+ }
109
+ } else if (!moduleExists("less")) {
110
+ info("Skipping Less support - less not installed")
111
+ } else if (!moduleExists("less-loader")) {
112
+ info("Skipping Less support - less-loader not installed")
113
+ }
114
+
115
+ // Stylus rules
116
+ debug("Checking for Stylus loader...")
117
+ if (moduleExists("stylus") && moduleExists("stylus-loader")) {
118
+ debug("stylus and stylus-loader found, loading Stylus rule configuration...")
119
+ const stylus = require("./stylus")
120
+ if (stylus) {
121
+ debug("Successfully added Stylus rule")
122
+ rules.push(stylus)
123
+ } else {
124
+ warn("stylus and stylus-loader found but rule configuration returned null")
125
+ }
126
+ } else if (!moduleExists("stylus")) {
127
+ info("Skipping Stylus support - stylus not installed")
128
+ } else if (!moduleExists("stylus-loader")) {
129
+ info("Skipping Stylus support - stylus-loader not installed")
130
+ }
131
+
132
+ // ERB template support
133
+ debug("Checking for ERB template support...")
134
+ const erb = require("./erb")
135
+
136
+ if (erb) {
137
+ debug("Successfully added ERB rule")
138
+ rules.push(erb)
139
+ } else {
140
+ info("Skipping ERB support - rails-erb-loader not installed")
141
+ }
142
+
143
+ // File/asset handling using Rspack's built-in asset modules
144
+ // This is a critical rule required for proper asset handling
145
+ debug("Adding file/asset handling rule...")
146
+ const file = require("./file")
147
+
148
+ if (!file) {
149
+ throw new Error(
150
+ "CRITICAL: file rule configuration returned null. " +
151
+ "Asset handling is required for proper bundling. " +
152
+ "Please ensure the file rule module exports a valid rule configuration."
153
+ )
154
+ }
155
+
156
+ debug("Successfully added file/asset rule")
157
+ rules.push(file)
158
+
159
+ // Raw file loading
160
+ // This is a critical rule required for raw file imports
161
+ debug("Adding raw file loading rule...")
162
+ const raw = require("./raw")
163
+
164
+ if (!raw) {
165
+ throw new Error(
166
+ "CRITICAL: raw rule configuration returned null. " +
167
+ "Raw file loading is required for proper bundling. " +
168
+ "Please ensure the raw rule module exports a valid rule configuration."
169
+ )
170
+ }
171
+
172
+ debug("Successfully added raw file rule")
173
+ rules.push(raw)
174
+
175
+ debug(`Rspack rules configuration complete. Total rules: ${rules.length}`)
176
+ export = rules
@@ -1,17 +1,21 @@
1
1
  /* eslint global-require: 0 */
2
2
 
3
- const getStyleRule = require("../utils/getStyleRule")
3
+ const { getStyleRule } = require("../utils/getStyleRule")
4
4
  const { canProcess, packageMajorVersion } = require("../utils/helpers")
5
5
  const { additional_paths: extraPaths } = require("../config")
6
6
 
7
- module.exports = canProcess("sass-loader", (resolvedPath) => {
7
+ export = canProcess("sass-loader", (resolvedPath: string) => {
8
8
  const optionKey =
9
9
  packageMajorVersion("sass-loader") > 15 ? "loadPaths" : "includePaths"
10
10
  return getStyleRule(/\.(scss|sass)(\.erb)?$/i, [
11
11
  {
12
12
  loader: resolvedPath,
13
13
  options: {
14
- sassOptions: { [optionKey]: extraPaths }
14
+ sourceMap: true,
15
+ sassOptions: {
16
+ [optionKey]: extraPaths,
17
+ quietDeps: true
18
+ }
15
19
  }
16
20
  }
17
21
  ])
@@ -1,23 +1,19 @@
1
- const path = require("path")
2
1
  const { canProcess } = require("../utils/helpers")
3
- const getStyleRule = require("../utils/getStyleRule")
2
+ const { getStyleRule } = require("../utils/getStyleRule")
4
3
 
5
4
  const {
6
5
  additional_paths: paths,
7
6
  source_path: sourcePath
8
7
  } = require("../config")
9
8
 
10
- module.exports = canProcess("stylus-loader", (resolvedPath) =>
9
+ export = canProcess("stylus-loader", (resolvedPath: string) =>
11
10
  getStyleRule(/\.(styl(us)?)(\.erb)?$/i, [
12
11
  {
13
12
  loader: resolvedPath,
14
13
  options: {
15
14
  stylusOptions: {
16
- include: [
17
- path.resolve(__dirname, "node_modules"),
18
- sourcePath,
19
- ...paths
20
- ]
15
+ // Additional paths for Stylus imports (node_modules is resolved automatically)
16
+ include: [sourcePath, ...paths]
21
17
  },
22
18
  sourceMap: true
23
19
  }
@@ -0,0 +1,10 @@
1
+ const { loaderMatches } = require("../utils/helpers")
2
+ const { getSwcLoaderConfig } = require("../swc")
3
+ const { javascript_transpiler: javascriptTranspiler } = require("../config")
4
+ const jscommon = require("./jscommon")
5
+
6
+ export = loaderMatches(javascriptTranspiler, "swc", () => ({
7
+ test: /\.(ts|tsx|js|jsx|mjs|coffee)?(\.erb)?$/,
8
+ ...jscommon,
9
+ use: ({ resource }: { resource: string }) => getSwcLoaderConfig(resource)
10
+ }))
@@ -0,0 +1,16 @@
1
+ /* eslint global-require: 0 */
2
+ /* eslint import/no-dynamic-require: 0 */
3
+
4
+ export = [
5
+ require("./raw"),
6
+ require("./file"),
7
+ require("./css"),
8
+ require("./sass"),
9
+ require("./babel"),
10
+ require("./swc"),
11
+ require("./esbuild"),
12
+ require("./erb"),
13
+ require("./coffee"),
14
+ require("./less"),
15
+ require("./stylus")
16
+ ].filter(Boolean)
@@ -0,0 +1,56 @@
1
+ /* eslint global-require: 0 */
2
+ /* eslint import/no-dynamic-require: 0 */
3
+
4
+ import { resolve } from "path"
5
+ import { existsSync } from "fs"
6
+ import { merge } from "webpack-merge"
7
+ import type { RuleSetRule } from "webpack"
8
+
9
+ const JSX_FILE_REGEX = /\.(jsx|tsx)(\.erb)?$/
10
+ const TYPESCRIPT_FILE_REGEX = /\.(ts|tsx)(\.erb)?$/
11
+
12
+ const isJsxFile = (filename: string): boolean =>
13
+ !!filename.match(JSX_FILE_REGEX)
14
+
15
+ const isTypescriptFile = (filename: string): boolean =>
16
+ !!filename.match(TYPESCRIPT_FILE_REGEX)
17
+
18
+ const getCustomConfig = (): Partial<RuleSetRule> => {
19
+ const path = resolve("config", "swc.config.js")
20
+ if (existsSync(path)) {
21
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
22
+ return require(path)
23
+ }
24
+ return {}
25
+ }
26
+
27
+ const getSwcLoaderConfig = (filenameToProcess: string): RuleSetRule => {
28
+ const customConfig = getCustomConfig()
29
+ const isTs = isTypescriptFile(filenameToProcess)
30
+ const isJsx = isJsxFile(filenameToProcess)
31
+ const jsxKey = isTs ? "tsx" : "jsx"
32
+
33
+ const defaultConfig: RuleSetRule = {
34
+ loader: require.resolve("swc-loader"),
35
+ options: {
36
+ jsc: {
37
+ parser: {
38
+ dynamicImport: true,
39
+ syntax: isTs ? "typescript" : "ecmascript",
40
+ [jsxKey]: isJsx
41
+ },
42
+ loose: false
43
+ },
44
+ sourceMaps: true,
45
+ env: {
46
+ coreJs: 3,
47
+ exclude: ["transform-typeof-symbol"],
48
+ mode: "entry"
49
+ }
50
+ }
51
+ }
52
+
53
+ return merge(defaultConfig, customConfig)
54
+ }
55
+
56
+ export { getSwcLoaderConfig }
@@ -0,0 +1,88 @@
1
+ # Shakapacker TypeScript Types
2
+
3
+ This directory exports all TypeScript types used in Shakapacker for easier consumer imports.
4
+
5
+ ## Usage
6
+
7
+ Instead of importing types from deep paths:
8
+
9
+ ```typescript
10
+ // ❌ Old way - importing from multiple deep paths
11
+ import type { Config } from 'shakapacker/package/types'
12
+ import type { WebpackConfigWithDevServer } from 'shakapacker/package/environments/types'
13
+ ```
14
+
15
+ You can now import all types from a single location:
16
+
17
+ ```typescript
18
+ // ✅ New way - single import path
19
+ import type {
20
+ Config,
21
+ WebpackConfigWithDevServer,
22
+ RspackConfigWithDevServer
23
+ } from 'shakapacker/types'
24
+ ```
25
+
26
+ ## Available Types
27
+
28
+ ### Core Configuration Types
29
+ - `Config` - Main Shakapacker configuration interface
30
+ - `YamlConfig` - YAML configuration structure
31
+ - `LegacyConfig` - Legacy configuration with deprecated options
32
+ - `Env` - Environment variables interface
33
+ - `DevServerConfig` - Development server configuration
34
+
35
+ ### Loader Types
36
+ - `ShakapackerLoader` - Loader interface
37
+ - `ShakapackerLoaderOptions` - Loader options interface
38
+ - `LoaderResolver` - Function type for resolving loaders
39
+ - `LoaderConfig` - Loader configuration interface
40
+
41
+ ### Webpack/Rspack Types
42
+ - `WebpackConfigWithDevServer` - Webpack config with dev server
43
+ - `RspackConfigWithDevServer` - Rspack config with dev server
44
+ - `RspackPluginInstance` - Rspack plugin instance type
45
+ - `RspackPlugin` - **⚠️ Deprecated:** Use `RspackPluginInstance` instead
46
+ - `RspackDevServerConfig` - Rspack dev server configuration
47
+ - `CompressionPluginOptions` - Options for compression plugin
48
+ - `CompressionPluginConstructor` - Constructor type for compression plugin
49
+ - `ReactRefreshWebpackPlugin` - React refresh plugin for Webpack
50
+ - `ReactRefreshRspackPlugin` - React refresh plugin for Rspack
51
+
52
+ ### Webpack-Specific Types
53
+ - `ShakapackerWebpackConfig` - Extended Webpack configuration
54
+ - `ShakapackerRule` - Extended Webpack rule
55
+ - `LoaderType` - String or loader object type
56
+ - `LoaderUtils` - Loader utility functions
57
+
58
+ ### Re-exported Types
59
+ - `WebpackConfiguration` - From 'webpack'
60
+ - `WebpackPluginInstance` - From 'webpack'
61
+ - `RuleSetRule` - From 'webpack'
62
+ - `NodeJSError` - Node.js error exception type
63
+
64
+ ## Example Usage
65
+
66
+ ```typescript
67
+ import type {
68
+ Config,
69
+ WebpackConfigWithDevServer
70
+ } from 'shakapacker/types'
71
+
72
+ const config: Config = {
73
+ source_path: 'app/javascript',
74
+ source_entry_path: 'packs',
75
+ public_root_path: 'public',
76
+ public_output_path: 'packs',
77
+ // ... other config
78
+ }
79
+
80
+ const webpackConfig: WebpackConfigWithDevServer = {
81
+ mode: 'development',
82
+ devServer: {
83
+ hot: true,
84
+ port: 3035
85
+ }
86
+ // ... other webpack config
87
+ }
88
+ ```
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Central type exports for Shakapacker
3
+ * This file re-exports all public TypeScript types for easier consumer imports
4
+ *
5
+ * @example
6
+ * ```typescript
7
+ * import type { Config, WebpackConfigWithDevServer } from 'shakapacker/types'
8
+ * ```
9
+ *
10
+ * @module shakapacker/types
11
+ */
12
+
13
+ // Core configuration types
14
+ export type {
15
+ Config,
16
+ YamlConfig,
17
+ LegacyConfig,
18
+ Env,
19
+ DevServerConfig
20
+ } from '../types'
21
+
22
+ // Loader types
23
+ export type {
24
+ ShakapackerLoader,
25
+ ShakapackerLoaderOptions,
26
+ LoaderResolver,
27
+ LoaderConfig
28
+ } from '../loaders'
29
+
30
+ // Webpack-specific types
31
+ export type {
32
+ ShakapackerWebpackConfig,
33
+ ShakapackerRule,
34
+ ShakapackerLoaderOptions as WebpackLoaderOptions,
35
+ ShakapackerLoader as WebpackLoader,
36
+ LoaderType,
37
+ LoaderUtils
38
+ } from '../webpack-types'
39
+
40
+ // Environment configuration types
41
+ export type {
42
+ WebpackConfigWithDevServer,
43
+ RspackPluginInstance,
44
+ RspackPlugin,
45
+ RspackDevServerConfig,
46
+ RspackConfigWithDevServer,
47
+ CompressionPluginOptions,
48
+ CompressionPluginConstructor,
49
+ ReactRefreshWebpackPlugin,
50
+ ReactRefreshRspackPlugin
51
+ } from '../environments/types'
52
+
53
+ // Node.js error type (re-exported for convenience)
54
+ export type NodeJSError = NodeJS.ErrnoException
55
+
56
+ // Re-export commonly used webpack types for convenience
57
+ export type {
58
+ Configuration as WebpackConfiguration,
59
+ WebpackPluginInstance,
60
+ RuleSetRule
61
+ } from 'webpack'
data/package/types.ts ADDED
@@ -0,0 +1,108 @@
1
+ import * as https from "node:https"
2
+
3
+ // Type for the raw YAML config file
4
+ export interface YamlConfig {
5
+ [environment: string]: Partial<Config>
6
+ }
7
+
8
+ // Type for backward compatibility
9
+ export interface LegacyConfig extends Config {
10
+ webpack_loader?: string
11
+ }
12
+
13
+ export interface Config {
14
+ source_path: string
15
+ source_entry_path: string
16
+ nested_entries: boolean
17
+ css_extract_ignore_order_warnings: boolean
18
+ public_root_path: string
19
+ public_output_path: string
20
+ private_output_path?: string
21
+ cache_path: string
22
+ webpack_compile_output: boolean
23
+ shakapacker_precompile: boolean
24
+ additional_paths: string[]
25
+ cache_manifest: boolean
26
+ javascript_transpiler: string
27
+ ensure_consistent_versioning: boolean
28
+ compiler_strategy: string
29
+ useContentHash: boolean
30
+ compile: boolean
31
+ outputPath: string
32
+ publicPath: string
33
+ publicPathWithoutCDN: string
34
+ manifestPath: string
35
+ manifest_path?: string
36
+ assets_bundler?: string
37
+ dev_server?: DevServerConfig
38
+ integrity?: {
39
+ enabled: boolean
40
+ cross_origin: string
41
+ hash_functions?: string[]
42
+ }
43
+ }
44
+
45
+ export interface Env {
46
+ railsEnv: string
47
+ nodeEnv: string
48
+ isProduction: boolean
49
+ isDevelopment: boolean
50
+ runningWebpackDevServer: boolean
51
+ }
52
+
53
+ type Header =
54
+ | Array<{ key: string; value: string }>
55
+ | Record<string, string | string[]>
56
+ type ServerType = "http" | "https" | "spdy"
57
+ type WebSocketType = "sockjs" | "ws"
58
+
59
+ /**
60
+ * This has the same keys and behavior as https://webpack.js.org/configuration/dev-server/ except:
61
+ * 1. `hot` is replaced by `hmr`;
62
+ * 2. Camel-cased properties are replaced by snake-cased ones.
63
+ * @see {import('webpack-dev-server').Configuration}
64
+ */
65
+ export interface DevServerConfig {
66
+ allowed_hosts?: "all" | "auto" | string | string[]
67
+ bonjour?: boolean | Record<string, unknown> // bonjour.BonjourOptions
68
+ client?: Record<string, unknown> // Client
69
+ compress?: boolean
70
+ dev_middleware?: Record<string, unknown> // webpackDevMiddleware.Options
71
+ headers?: Header | (() => Header)
72
+ history_api_fallback?: boolean | Record<string, unknown> // HistoryApiFallbackOptions
73
+ hmr?: "only" | boolean
74
+ host?: "local-ip" | "local-ipv4" | "local-ipv6" | string
75
+ http2?: boolean
76
+ https?: boolean | https.ServerOptions
77
+ ipc?: boolean | string
78
+ magic_html?: boolean
79
+ live_reload?: boolean
80
+ inline_css?: boolean
81
+ env_prefix?: string
82
+ open?:
83
+ | boolean
84
+ | string
85
+ | string[]
86
+ | Record<string, unknown>
87
+ | Record<string, unknown>[]
88
+ port?: "auto" | string | number
89
+ proxy?: unknown // ProxyConfigMap | ProxyConfigArray
90
+ setup_exit_signals?: boolean
91
+ static?: boolean | string | unknown // Static | Array<string | Static>
92
+ watch_files?: string | string[] | unknown // WatchFiles | Array<WatchFiles | string>
93
+ web_socket_server?:
94
+ | string
95
+ | boolean
96
+ | WebSocketType
97
+ | {
98
+ type?: string | boolean | WebSocketType
99
+ options?: Record<string, unknown>
100
+ }
101
+ server?:
102
+ | string
103
+ | boolean
104
+ | ServerType
105
+ | { type?: string | boolean | ServerType; options?: https.ServerOptions }
106
+ [otherWebpackDevServerConfigKey: string]: unknown
107
+ }
108
+
@@ -0,0 +1,6 @@
1
+ import { resolve } from "path"
2
+
3
+ const configPath: string =
4
+ process.env.SHAKAPACKER_CONFIG || resolve("config", "shakapacker.yml")
5
+
6
+ export = configPath
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Debug utility for Shakapacker
3
+ * Provides conditional logging based on environment variables
4
+ */
5
+
6
+ const isDebugMode = (): boolean => {
7
+ // Explicitly check for debug mode being disabled
8
+ if (process.env.SHAKAPACKER_DEBUG === "false") {
9
+ return false
10
+ }
11
+
12
+ // Support both SHAKAPACKER_DEBUG (new) and DEBUG_SHAKAPACKER (legacy) for backwards compatibility
13
+ return (
14
+ process.env.SHAKAPACKER_DEBUG === "true" ||
15
+ process.env.DEBUG_SHAKAPACKER === "true"
16
+ )
17
+ }
18
+
19
+ const debug = (message: string, ...args: unknown[]): void => {
20
+ if (isDebugMode()) {
21
+ // eslint-disable-next-line no-console
22
+ console.log(`[Shakapacker] ${message}`, ...args)
23
+ }
24
+ }
25
+
26
+ const warn = (message: string, ...args: unknown[]): void => {
27
+ // eslint-disable-next-line no-console
28
+ console.warn(`[Shakapacker] WARNING: ${message}`, ...args)
29
+ }
30
+
31
+ const error = (message: string, ...args: unknown[]): void => {
32
+ // eslint-disable-next-line no-console
33
+ console.error(`[Shakapacker] ERROR: ${message}`, ...args)
34
+ }
35
+
36
+ const info = (message: string, ...args: unknown[]): void => {
37
+ if (isDebugMode()) {
38
+ // eslint-disable-next-line no-console
39
+ console.info(`[Shakapacker] INFO: ${message}`, ...args)
40
+ }
41
+ }
42
+
43
+ export = {
44
+ debug,
45
+ warn,
46
+ error,
47
+ info,
48
+ isDebugMode
49
+ }
@@ -0,0 +1,4 @@
1
+ import { resolve } from "path"
2
+
3
+ const path: string = resolve(__dirname, "../../lib/install/config/shakapacker.yml")
4
+ export = path