shakapacker 8.4.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.
Files changed (265) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/commands/address-review.md +206 -0
  3. data/.claude/commands/update-changelog.md +354 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +6 -9
  5. data/.github/ISSUE_TEMPLATE/feature_request.md +6 -8
  6. data/.github/STATUS.md +1 -0
  7. data/.github/actionlint-matcher.json +17 -0
  8. data/.github/workflows/claude-code-review.yml +45 -0
  9. data/.github/workflows/claude.yml +55 -0
  10. data/.github/workflows/dummy.yml +18 -5
  11. data/.github/workflows/eslint-validation.yml +46 -0
  12. data/.github/workflows/generator.yml +38 -22
  13. data/.github/workflows/node.yml +116 -2
  14. data/.github/workflows/ruby.yml +57 -15
  15. data/.github/workflows/test-bundlers.yml +180 -0
  16. data/.gitignore +27 -0
  17. data/.husky/pre-commit +2 -0
  18. data/.npmignore +56 -0
  19. data/.prettierignore +7 -0
  20. data/.rubocop.yml +2 -0
  21. data/.yalcignore +26 -0
  22. data/CHANGELOG.md +487 -19
  23. data/CLAUDE.md +63 -0
  24. data/CONTRIBUTING.md +268 -21
  25. data/ESLINT_TECHNICAL_DEBT.md +165 -0
  26. data/README.md +497 -137
  27. data/Rakefile +44 -4
  28. data/TODO.md +58 -0
  29. data/TODO_v9.md +97 -0
  30. data/bin/conductor-exec +24 -0
  31. data/bin/shakapacker-config +11 -0
  32. data/conductor-setup.sh +147 -0
  33. data/conductor.json +9 -0
  34. data/docs/api-reference.md +519 -0
  35. data/docs/cdn_setup.md +384 -0
  36. data/docs/common-upgrades.md +695 -0
  37. data/docs/configuration.md +845 -0
  38. data/docs/css-modules-export-mode.md +566 -0
  39. data/docs/customizing_babel_config.md +16 -16
  40. data/docs/deployment.md +78 -7
  41. data/docs/developing_shakapacker.md +6 -0
  42. data/docs/early_hints.md +433 -0
  43. data/docs/early_hints_manual_api.md +454 -0
  44. data/docs/feature_testing.md +492 -0
  45. data/docs/node_package_api.md +70 -0
  46. data/docs/optional-peer-dependencies.md +203 -0
  47. data/docs/peer-dependencies.md +71 -0
  48. data/docs/precompile_hook.md +486 -0
  49. data/docs/preventing_fouc.md +132 -0
  50. data/docs/react.md +58 -48
  51. data/docs/releasing.md +288 -0
  52. data/docs/rspack.md +218 -0
  53. data/docs/rspack_migration_guide.md +862 -0
  54. data/docs/sprockets.md +1 -0
  55. data/docs/style_loader_vs_mini_css.md +12 -12
  56. data/docs/subresource_integrity.md +13 -7
  57. data/docs/transpiler-migration.md +212 -0
  58. data/docs/transpiler-performance.md +200 -0
  59. data/docs/troubleshooting.md +272 -24
  60. data/docs/typescript-migration.md +388 -0
  61. data/docs/typescript.md +103 -0
  62. data/docs/using_esbuild_loader.md +12 -12
  63. data/docs/using_swc_loader.md +121 -16
  64. data/docs/v6_upgrade.md +42 -19
  65. data/docs/v7_upgrade.md +8 -6
  66. data/docs/v8_upgrade.md +13 -12
  67. data/docs/v9_upgrade.md +616 -0
  68. data/eslint.config.fast.js +254 -0
  69. data/eslint.config.js +309 -0
  70. data/jest.config.js +8 -1
  71. data/knip.ts +61 -0
  72. data/lib/install/bin/shakapacker +4 -6
  73. data/lib/install/bin/shakapacker-config +11 -0
  74. data/lib/install/bin/shakapacker-dev-server +1 -1
  75. data/lib/install/binstubs.rb +6 -2
  76. data/lib/install/config/rspack/rspack.config.js +6 -0
  77. data/lib/install/config/rspack/rspack.config.ts +7 -0
  78. data/lib/install/config/shakapacker.yml +75 -12
  79. data/lib/install/config/webpack/webpack.config.ts +7 -0
  80. data/lib/install/package.json +38 -0
  81. data/lib/install/template.rb +207 -45
  82. data/lib/shakapacker/build_config_loader.rb +147 -0
  83. data/lib/shakapacker/bundler_switcher.rb +415 -0
  84. data/lib/shakapacker/compiler.rb +87 -0
  85. data/lib/shakapacker/configuration.rb +475 -6
  86. data/lib/shakapacker/dev_server.rb +88 -1
  87. data/lib/shakapacker/dev_server_runner.rb +240 -6
  88. data/lib/shakapacker/doctor.rb +1191 -0
  89. data/lib/shakapacker/env.rb +19 -3
  90. data/lib/shakapacker/helper.rb +411 -14
  91. data/lib/shakapacker/install/env.rb +33 -0
  92. data/lib/shakapacker/instance.rb +93 -4
  93. data/lib/shakapacker/manifest.rb +167 -30
  94. data/lib/shakapacker/railtie.rb +4 -0
  95. data/lib/shakapacker/rspack_runner.rb +19 -0
  96. data/lib/shakapacker/runner.rb +668 -9
  97. data/lib/shakapacker/swc_migrator.rb +384 -0
  98. data/lib/shakapacker/utils/manager.rb +2 -0
  99. data/lib/shakapacker/utils/version_syntax_converter.rb +1 -1
  100. data/lib/shakapacker/version.rb +1 -1
  101. data/lib/shakapacker/version_checker.rb +1 -1
  102. data/lib/shakapacker/webpack_runner.rb +4 -42
  103. data/lib/shakapacker.rb +159 -1
  104. data/lib/tasks/shakapacker/binstubs.rake +4 -2
  105. data/lib/tasks/shakapacker/check_binstubs.rake +2 -2
  106. data/lib/tasks/shakapacker/doctor.rake +48 -0
  107. data/lib/tasks/shakapacker/export_bundler_config.rake +68 -0
  108. data/lib/tasks/shakapacker/install.rake +16 -4
  109. data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
  110. data/lib/tasks/shakapacker/switch_bundler.rake +72 -0
  111. data/lib/tasks/shakapacker.rake +2 -0
  112. data/package/.npmignore +4 -0
  113. data/package/babel/preset.ts +59 -0
  114. data/package/config.ts +189 -0
  115. data/package/configExporter/buildValidator.ts +906 -0
  116. data/package/configExporter/cli.ts +1748 -0
  117. data/package/configExporter/configDocs.ts +102 -0
  118. data/package/configExporter/configFile.ts +663 -0
  119. data/package/configExporter/fileWriter.ts +112 -0
  120. data/package/configExporter/index.ts +15 -0
  121. data/package/configExporter/types.ts +159 -0
  122. data/package/configExporter/yamlSerializer.ts +391 -0
  123. data/package/dev_server.ts +27 -0
  124. data/package/env.ts +92 -0
  125. data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +36 -0
  126. data/package/environments/base.ts +147 -0
  127. data/package/environments/development.ts +88 -0
  128. data/package/environments/production.ts +82 -0
  129. data/package/environments/test.ts +55 -0
  130. data/package/environments/types.ts +98 -0
  131. data/package/esbuild/index.ts +40 -0
  132. data/package/index.d.ts +68 -93
  133. data/package/index.d.ts.template +72 -0
  134. data/package/index.ts +104 -0
  135. data/package/loaders.d.ts +28 -0
  136. data/package/optimization/rspack.ts +36 -0
  137. data/package/optimization/webpack.ts +55 -0
  138. data/package/plugins/envFilter.ts +82 -0
  139. data/package/plugins/rspack.ts +119 -0
  140. data/package/plugins/webpack.ts +82 -0
  141. data/package/rspack/index.ts +91 -0
  142. data/package/rules/{babel.js → babel.ts} +2 -2
  143. data/package/rules/{coffee.js → coffee.ts} +1 -1
  144. data/package/rules/css.ts +3 -0
  145. data/package/rules/{erb.js → erb.ts} +1 -1
  146. data/package/rules/esbuild.ts +10 -0
  147. data/package/rules/file.ts +41 -0
  148. data/package/rules/{jscommon.js → jscommon.ts} +5 -4
  149. data/package/rules/{less.js → less.ts} +4 -4
  150. data/package/rules/raw.ts +28 -0
  151. data/package/rules/rspack.ts +174 -0
  152. data/package/rules/sass.ts +21 -0
  153. data/package/rules/{stylus.js → stylus.ts} +4 -8
  154. data/package/rules/swc.ts +10 -0
  155. data/package/rules/{index.js → webpack.ts} +1 -2
  156. data/package/swc/index.ts +54 -0
  157. data/package/types/README.md +90 -0
  158. data/package/types/index.ts +69 -0
  159. data/package/types.ts +105 -0
  160. data/package/utils/bundlerUtils.ts +232 -0
  161. data/package/utils/configPath.ts +6 -0
  162. data/package/utils/debug.ts +45 -0
  163. data/package/utils/defaultConfigPath.ts +7 -0
  164. data/package/utils/ensureManifestExists.ts +17 -0
  165. data/package/utils/errorCodes.ts +249 -0
  166. data/package/utils/errorHelpers.ts +152 -0
  167. data/package/utils/getStyleRule.ts +75 -0
  168. data/package/utils/helpers.ts +99 -0
  169. data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
  170. data/package/utils/pathValidation.ts +207 -0
  171. data/package/utils/requireOrError.ts +24 -0
  172. data/package/utils/snakeToCamelCase.ts +5 -0
  173. data/package/utils/typeGuards.ts +388 -0
  174. data/package/utils/validateDependencies.ts +61 -0
  175. data/package/webpack-types.d.ts +33 -0
  176. data/package/webpackDevServerConfig.ts +130 -0
  177. data/package.json +157 -18
  178. data/scripts/remove-use-strict.js +44 -0
  179. data/scripts/type-check-no-emit.js +27 -0
  180. data/shakapacker.gemspec +4 -2
  181. data/sig/shakapacker/commands.rbs +35 -0
  182. data/sig/shakapacker/compiler.rbs +65 -0
  183. data/sig/shakapacker/compiler_strategy.rbs +41 -0
  184. data/sig/shakapacker/configuration.rbs +140 -0
  185. data/sig/shakapacker/dev_server.rbs +56 -0
  186. data/sig/shakapacker/env.rbs +25 -0
  187. data/sig/shakapacker/helper.rbs +98 -0
  188. data/sig/shakapacker/instance.rbs +46 -0
  189. data/sig/shakapacker/manifest.rbs +69 -0
  190. data/sig/shakapacker/version.rbs +4 -0
  191. data/sig/shakapacker.rbs +66 -0
  192. data/test/configExporter/buildValidator.test.js +1295 -0
  193. data/test/configExporter/configFile.test.js +393 -0
  194. data/test/configExporter/integration.test.js +262 -0
  195. data/test/helpers.js +1 -1
  196. data/test/package/bundlerUtils.rspack.test.js +145 -0
  197. data/test/package/bundlerUtils.test.js +97 -0
  198. data/test/package/config.test.js +14 -0
  199. data/test/package/configExporter/cli.test.js +440 -0
  200. data/test/package/configExporter/types.test.js +163 -0
  201. data/test/package/configExporter.test.js +491 -0
  202. data/test/package/env.test.js +42 -7
  203. data/test/package/environments/base.test.js +14 -4
  204. data/test/package/helpers.test.js +2 -2
  205. data/test/package/plugins/envFiltering.test.js +453 -0
  206. data/test/package/plugins/webpackSubresourceIntegrity.test.js +89 -0
  207. data/test/package/rspack/index.test.js +293 -0
  208. data/test/package/rspack/optimization.test.js +86 -0
  209. data/test/package/rspack/plugins.test.js +185 -0
  210. data/test/package/rspack/rules.test.js +229 -0
  211. data/test/package/rules/babel.test.js +65 -38
  212. data/test/package/rules/esbuild.test.js +13 -4
  213. data/test/package/rules/file.test.js +7 -1
  214. data/test/package/rules/raw.test.js +40 -7
  215. data/test/package/rules/sass-version-parsing.test.js +71 -0
  216. data/test/package/rules/sass.test.js +11 -6
  217. data/test/package/rules/sass1.test.js +8 -5
  218. data/test/package/rules/sass16.test.js +24 -0
  219. data/test/package/rules/swc.test.js +50 -39
  220. data/test/package/rules/webpack.test.js +35 -0
  221. data/test/package/staging.test.js +4 -3
  222. data/test/package/transpiler-defaults.test.js +169 -0
  223. data/test/package/utils/ensureManifestExists.test.js +51 -0
  224. data/test/package/yamlSerializer.test.js +204 -0
  225. data/test/peer-dependencies.sh +85 -0
  226. data/test/resolver.js +34 -3
  227. data/test/scripts/remove-use-strict.test.js +125 -0
  228. data/test/typescript/build.test.js +118 -0
  229. data/test/typescript/environments.test.js +107 -0
  230. data/test/typescript/pathValidation.test.js +186 -0
  231. data/test/typescript/requireOrError.test.js +49 -0
  232. data/test/typescript/securityValidation.test.js +182 -0
  233. data/tools/README.md +134 -0
  234. data/tools/css-modules-v9-codemod.js +179 -0
  235. data/tsconfig.eslint.json +9 -0
  236. data/tsconfig.json +38 -0
  237. data/yarn.lock +3202 -1097
  238. metadata +212 -44
  239. data/.eslintignore +0 -4
  240. data/.eslintrc.js +0 -36
  241. data/Gemfile.lock +0 -251
  242. data/package/babel/preset.js +0 -48
  243. data/package/config.js +0 -56
  244. data/package/dev_server.js +0 -23
  245. data/package/env.js +0 -48
  246. data/package/environments/base.js +0 -171
  247. data/package/environments/development.js +0 -13
  248. data/package/environments/production.js +0 -88
  249. data/package/environments/test.js +0 -3
  250. data/package/esbuild/index.js +0 -40
  251. data/package/index.js +0 -40
  252. data/package/rules/css.js +0 -3
  253. data/package/rules/esbuild.js +0 -10
  254. data/package/rules/file.js +0 -29
  255. data/package/rules/raw.js +0 -5
  256. data/package/rules/sass.js +0 -18
  257. data/package/rules/swc.js +0 -10
  258. data/package/swc/index.js +0 -50
  259. data/package/utils/configPath.js +0 -4
  260. data/package/utils/defaultConfigPath.js +0 -2
  261. data/package/utils/getStyleRule.js +0 -40
  262. data/package/utils/helpers.js +0 -62
  263. data/package/utils/snakeToCamelCase.js +0 -5
  264. data/package/webpackDevServerConfig.js +0 -71
  265. data/test/package/rules/index.test.js +0 -16
@@ -0,0 +1,254 @@
1
+ // Fast ESLint config for quick development feedback
2
+ // Skips type-aware rules that require TypeScript compilation
3
+
4
+ const { FlatCompat } = require("@eslint/eslintrc")
5
+ const js = require("@eslint/js")
6
+ const typescriptParser = require("@typescript-eslint/parser")
7
+ const typescriptPlugin = require("@typescript-eslint/eslint-plugin")
8
+ const jestPlugin = require("eslint-plugin-jest")
9
+ const prettierConfig = require("eslint-config-prettier")
10
+
11
+ const compat = new FlatCompat({
12
+ baseDirectory: __dirname,
13
+ recommendedConfig: js.configs.recommended
14
+ })
15
+
16
+ module.exports = [
17
+ // Global ignores (replaces .eslintignore)
18
+ {
19
+ ignores: [
20
+ "lib/**", // Ruby files, not JavaScript
21
+ "**/node_modules/**", // Third-party dependencies
22
+ "vendor/**", // Vendored dependencies
23
+ "spec/**", // Ruby specs, not JavaScript
24
+ "package/**/*.js", // Generated/compiled JavaScript from TypeScript
25
+ "package/**/*.d.ts" // Generated TypeScript declaration files
26
+ ]
27
+ },
28
+
29
+ // Global linter options
30
+ {
31
+ linterOptions: {
32
+ reportUnusedDisableDirectives: "error",
33
+ reportUnusedInlineConfigs: "error"
34
+ }
35
+ },
36
+
37
+ // Base config for all JS files
38
+ ...compat.extends("airbnb"),
39
+ {
40
+ languageOptions: {
41
+ ecmaVersion: 2020,
42
+ sourceType: "module",
43
+ globals: {
44
+ // Browser globals
45
+ window: "readonly",
46
+ document: "readonly",
47
+ navigator: "readonly",
48
+ console: "readonly",
49
+ // Node globals
50
+ process: "readonly",
51
+ __dirname: "readonly",
52
+ __filename: "readonly",
53
+ module: "readonly",
54
+ require: "readonly",
55
+ exports: "readonly",
56
+ global: "readonly",
57
+ Buffer: "readonly"
58
+ }
59
+ },
60
+ rules: {
61
+ // Webpack handles module resolution, not ESLint
62
+ "import/no-unresolved": "off",
63
+ // Allow importing devDependencies in config/test files
64
+ "import/no-extraneous-dependencies": "off",
65
+ // TypeScript handles extensions, not needed for JS imports
66
+ "import/extensions": "off",
67
+ indent: ["error", 2],
68
+ // Allow for...of loops - modern JS syntax
69
+ "no-restricted-syntax": "off",
70
+ // Allow console statements - used for debugging/logging throughout
71
+ "no-console": "off"
72
+ },
73
+ settings: {
74
+ react: {
75
+ // Suppress "react package not installed" warning
76
+ // This project doesn't use React but airbnb config requires react-plugin
77
+ version: "999.999.999"
78
+ }
79
+ }
80
+ },
81
+
82
+ // Jest test files
83
+ {
84
+ files: ["test/**"],
85
+ plugins: {
86
+ jest: jestPlugin
87
+ },
88
+ languageOptions: {
89
+ globals: {
90
+ ...jestPlugin.environments.globals.globals
91
+ }
92
+ },
93
+ rules: {
94
+ ...jestPlugin.configs.recommended.rules,
95
+ ...jestPlugin.configs.style.rules,
96
+ "global-require": "off",
97
+ "jest/prefer-called-with": "error",
98
+ "jest/no-conditional-in-test": "error",
99
+ "jest/no-test-return-statement": "error",
100
+ "jest/prefer-expect-resolves": "error",
101
+ "jest/require-to-throw-message": "error",
102
+ "jest/require-top-level-describe": "error",
103
+ "jest/prefer-hooks-on-top": "error",
104
+ "jest/prefer-lowercase-title": [
105
+ "error",
106
+ { ignoreTopLevelDescribe: true }
107
+ ],
108
+ "jest/prefer-spy-on": "error",
109
+ "jest/prefer-strict-equal": "error",
110
+ "jest/prefer-todo": "error"
111
+ }
112
+ },
113
+
114
+ // TypeScript files - fast mode without type-aware linting
115
+ {
116
+ files: ["**/*.ts", "**/*.tsx"],
117
+ languageOptions: {
118
+ parser: typescriptParser,
119
+ parserOptions: {
120
+ // No project specified - disables type-aware linting
121
+ ecmaVersion: 2020,
122
+ sourceType: "module"
123
+ }
124
+ },
125
+ plugins: {
126
+ "@typescript-eslint": typescriptPlugin
127
+ },
128
+ rules: {
129
+ ...typescriptPlugin.configs.recommended.rules,
130
+ // Same rules as main config minus type-aware ones
131
+ "import/no-unresolved": "off",
132
+ "import/no-extraneous-dependencies": "off",
133
+ "import/extensions": "off",
134
+ "no-use-before-define": "off",
135
+ "@typescript-eslint/no-use-before-define": ["error"],
136
+ "@typescript-eslint/no-unused-vars": [
137
+ "error",
138
+ { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }
139
+ ],
140
+ "@typescript-eslint/no-explicit-any": "error",
141
+ "@typescript-eslint/explicit-module-boundary-types": "off",
142
+ "no-undef": "off"
143
+ }
144
+ },
145
+
146
+ // Global rule for all TypeScript files in package/
147
+ // Suppress require() imports - these are intentional for CommonJS compatibility
148
+ // Will be addressed in Phase 3 (breaking changes) - see #708
149
+ {
150
+ files: ["package/**/*.ts"],
151
+ rules: {
152
+ "@typescript-eslint/no-require-imports": "off",
153
+ "global-require": "off",
154
+ "import/no-import-module-exports": "off"
155
+ }
156
+ },
157
+
158
+ // Consolidated override for package/config.ts and package/babel/preset.ts
159
+ {
160
+ files: ["package/babel/preset.ts", "package/config.ts"],
161
+ rules: {
162
+ "@typescript-eslint/no-unused-vars": "off",
163
+ "import/order": "off",
164
+ "import/newline-after-import": "off",
165
+ "import/first": "off",
166
+ "@typescript-eslint/no-explicit-any": "off",
167
+ "no-useless-escape": "off"
168
+ }
169
+ },
170
+
171
+ // configExporter module overrides
172
+ {
173
+ files: ["package/configExporter/**/*.ts"],
174
+ rules: {
175
+ "@typescript-eslint/no-use-before-define": "off",
176
+ "import/no-dynamic-require": "off",
177
+ "class-methods-use-this": "off",
178
+ "import/prefer-default-export": "off",
179
+ "no-underscore-dangle": "off",
180
+ "no-restricted-globals": "off",
181
+ "@typescript-eslint/no-unused-vars": "off",
182
+ "@typescript-eslint/no-explicit-any": "off"
183
+ }
184
+ },
185
+
186
+ // Utils module overrides
187
+ {
188
+ files: [
189
+ "package/utils/inliningCss.ts",
190
+ "package/utils/errorCodes.ts",
191
+ "package/utils/errorHelpers.ts",
192
+ "package/utils/pathValidation.ts",
193
+ "package/utils/getStyleRule.ts",
194
+ "package/utils/helpers.ts",
195
+ "package/utils/validateDependencies.ts",
196
+ "package/webpackDevServerConfig.ts"
197
+ ],
198
+ rules: {
199
+ "@typescript-eslint/no-explicit-any": "off",
200
+ "no-useless-escape": "off"
201
+ }
202
+ },
203
+
204
+ // Plugins and optimization overrides
205
+ {
206
+ files: ["package/plugins/**/*.ts", "package/optimization/**/*.ts"],
207
+ rules: {
208
+ "import/prefer-default-export": "off"
209
+ }
210
+ },
211
+
212
+ // Rules, rspack, swc, esbuild, and other modules
213
+ {
214
+ files: [
215
+ "package/index.ts",
216
+ "package/rspack/index.ts",
217
+ "package/rules/**/*.ts",
218
+ "package/swc/index.ts",
219
+ "package/esbuild/index.ts",
220
+ "package/dev_server.ts",
221
+ "package/env.ts"
222
+ ],
223
+ rules: {
224
+ "@typescript-eslint/no-unused-vars": "off",
225
+ "import/prefer-default-export": "off",
226
+ "no-underscore-dangle": "off"
227
+ }
228
+ },
229
+
230
+ // Environments module overrides
231
+ {
232
+ files: ["package/environments/**/*.ts"],
233
+ rules: {
234
+ "import/prefer-default-export": "off",
235
+ "no-underscore-dangle": "off"
236
+ }
237
+ },
238
+
239
+ // Type tests are intentionally unused - they test type compatibility
240
+ {
241
+ files: ["package/**/__type-tests__/**/*.ts"],
242
+ rules: {
243
+ "@typescript-eslint/no-unused-vars": "off"
244
+ }
245
+ },
246
+
247
+ // Note: Type-aware rule overrides from main config (e.g., @typescript-eslint/no-unsafe-*,
248
+ // @typescript-eslint/restrict-template-expressions) are intentionally omitted here since
249
+ // fast mode doesn't enable type-aware linting (no parserOptions.project specified).
250
+ // This keeps fast mode performant while maintaining consistency for non-type-aware rules.
251
+
252
+ // Prettier config must be last to override other configs
253
+ prettierConfig
254
+ ]
data/eslint.config.js ADDED
@@ -0,0 +1,309 @@
1
+ const { FlatCompat } = require("@eslint/eslintrc")
2
+ const js = require("@eslint/js")
3
+ const typescriptParser = require("@typescript-eslint/parser")
4
+ const typescriptPlugin = require("@typescript-eslint/eslint-plugin")
5
+ const jestPlugin = require("eslint-plugin-jest")
6
+ const prettierConfig = require("eslint-config-prettier")
7
+
8
+ const compat = new FlatCompat({
9
+ baseDirectory: __dirname,
10
+ recommendedConfig: js.configs.recommended
11
+ })
12
+
13
+ module.exports = [
14
+ // Global ignores (replaces .eslintignore)
15
+ {
16
+ ignores: [
17
+ "lib/**", // Ruby files, not JavaScript
18
+ "**/node_modules/**", // Third-party dependencies
19
+ "vendor/**", // Vendored dependencies
20
+ "spec/**", // Ruby specs, not JavaScript
21
+ "package/**/*.js", // Generated/compiled JavaScript from TypeScript
22
+ "package/**/*.d.ts" // Generated TypeScript declaration files
23
+ ]
24
+ },
25
+
26
+ // Global linter options
27
+ {
28
+ linterOptions: {
29
+ reportUnusedDisableDirectives: "error",
30
+ reportUnusedInlineConfigs: "error"
31
+ }
32
+ },
33
+
34
+ // Base config for all JS files
35
+ ...compat.extends("airbnb"),
36
+ {
37
+ languageOptions: {
38
+ ecmaVersion: 2020,
39
+ sourceType: "module",
40
+ globals: {
41
+ // Browser globals
42
+ window: "readonly",
43
+ document: "readonly",
44
+ navigator: "readonly",
45
+ console: "readonly",
46
+ // Node globals
47
+ process: "readonly",
48
+ __dirname: "readonly",
49
+ __filename: "readonly",
50
+ module: "readonly",
51
+ require: "readonly",
52
+ exports: "readonly",
53
+ global: "readonly",
54
+ Buffer: "readonly"
55
+ }
56
+ },
57
+ rules: {
58
+ // Webpack handles module resolution, not ESLint
59
+ "import/no-unresolved": "off",
60
+ // Allow importing devDependencies in config/test files
61
+ "import/no-extraneous-dependencies": "off",
62
+ // TypeScript handles extensions, not needed for JS imports
63
+ "import/extensions": "off",
64
+ indent: ["error", 2],
65
+ // Allow for...of loops - modern JS syntax, won't pollute client code
66
+ "no-restricted-syntax": "off",
67
+ // Allow console statements - used for debugging/logging throughout
68
+ "no-console": "off"
69
+ },
70
+ settings: {
71
+ react: {
72
+ // Suppress "react package not installed" warning
73
+ // This project doesn't use React but airbnb config requires react-plugin
74
+ version: "999.999.999"
75
+ }
76
+ }
77
+ },
78
+
79
+ // Jest test files
80
+ {
81
+ files: ["test/**"],
82
+ plugins: {
83
+ jest: jestPlugin
84
+ },
85
+ languageOptions: {
86
+ globals: {
87
+ ...jestPlugin.environments.globals.globals
88
+ }
89
+ },
90
+ rules: {
91
+ ...jestPlugin.configs.recommended.rules,
92
+ ...jestPlugin.configs.style.rules,
93
+ "global-require": "off",
94
+ "jest/prefer-called-with": "error",
95
+ "jest/no-conditional-in-test": "error",
96
+ "jest/no-test-return-statement": "error",
97
+ "jest/prefer-expect-resolves": "error",
98
+ "jest/require-to-throw-message": "error",
99
+ "jest/require-top-level-describe": "error",
100
+ "jest/prefer-hooks-on-top": "error",
101
+ "jest/prefer-lowercase-title": [
102
+ "error",
103
+ { ignoreTopLevelDescribe: true }
104
+ ],
105
+ "jest/prefer-spy-on": "error",
106
+ "jest/prefer-strict-equal": "error",
107
+ "jest/prefer-todo": "error"
108
+ }
109
+ },
110
+
111
+ // TypeScript files
112
+ {
113
+ files: ["**/*.ts", "**/*.tsx"],
114
+ languageOptions: {
115
+ parser: typescriptParser,
116
+ parserOptions: {
117
+ // Enables type-aware linting for better type safety
118
+ // Note: This can slow down linting on large codebases
119
+ // Consider using --cache flag with ESLint if performance degrades
120
+ project: "./tsconfig.eslint.json",
121
+ tsconfigRootDir: __dirname
122
+ }
123
+ },
124
+ plugins: {
125
+ "@typescript-eslint": typescriptPlugin
126
+ },
127
+ rules: {
128
+ ...typescriptPlugin.configs.recommended.rules,
129
+ ...typescriptPlugin.configs["recommended-requiring-type-checking"].rules,
130
+ // TypeScript compiler handles module resolution
131
+ "import/no-unresolved": "off",
132
+ // Allow importing devDependencies in TypeScript files
133
+ "import/no-extraneous-dependencies": "off",
134
+ // TypeScript handles file extensions via moduleResolution
135
+ "import/extensions": "off",
136
+ // Disable base rule in favor of TypeScript version
137
+ "no-use-before-define": "off",
138
+ "@typescript-eslint/no-use-before-define": ["error"],
139
+ // Allow unused vars if they start with underscore (convention for ignored params and type tests)
140
+ "@typescript-eslint/no-unused-vars": [
141
+ "error",
142
+ { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }
143
+ ],
144
+ // Strict: no 'any' types allowed - use 'unknown' or specific types instead
145
+ "@typescript-eslint/no-explicit-any": "error",
146
+ // Allow implicit return types - TypeScript can infer them
147
+ "@typescript-eslint/explicit-module-boundary-types": "off",
148
+ // Disable no-undef for TypeScript - TypeScript compiler handles this
149
+ // This prevents false positives for ambient types like NodeJS.ProcessEnv
150
+ "no-undef": "off"
151
+ }
152
+ },
153
+
154
+ // Global rule for all TypeScript files in package/
155
+ // Suppress require() imports - these are intentional for CommonJS compatibility
156
+ // Will be addressed in Phase 3 (breaking changes) - see #708
157
+ {
158
+ files: ["package/**/*.ts"],
159
+ rules: {
160
+ "@typescript-eslint/no-require-imports": "off",
161
+ "global-require": "off",
162
+ "import/no-import-module-exports": "off"
163
+ }
164
+ },
165
+
166
+ // Temporary overrides for files with remaining errors
167
+ // See ESLINT_TECHNICAL_DEBT.md for detailed documentation
168
+ //
169
+ // These overrides suppress ~94 type safety errors that require:
170
+ // 1. Major type refactoring (any/unsafe-* rules)
171
+ // 2. Proper type definitions for config objects
172
+ //
173
+ // GitHub Issue tracking this technical debt:
174
+ // - #790: TypeScript ESLint Phase 2b: Type Safety Improvements (~94 errors)
175
+ {
176
+ // Consolidated override for package/config.ts and package/babel/preset.ts
177
+ // Combines rules from both previous override blocks to avoid duplication
178
+ files: ["package/babel/preset.ts", "package/config.ts"],
179
+ rules: {
180
+ "@typescript-eslint/no-unused-vars": "off",
181
+ "@typescript-eslint/no-unsafe-call": "off",
182
+ "import/order": "off",
183
+ "import/newline-after-import": "off",
184
+ "import/first": "off",
185
+ "@typescript-eslint/no-unsafe-assignment": "off",
186
+ "@typescript-eslint/no-unsafe-member-access": "off",
187
+ "@typescript-eslint/no-unsafe-argument": "off",
188
+ "@typescript-eslint/no-explicit-any": "off",
189
+ "no-useless-escape": "off"
190
+ }
191
+ },
192
+ {
193
+ // #707: Significant type safety improvements in configExporter module!
194
+ // - configFile.ts: ✅ Fully type-safe (0 type errors)
195
+ // - buildValidator.ts: ✅ Fully type-safe (0 type errors)
196
+ // - yamlSerializer.ts: ✅ Fully type-safe (0 type errors)
197
+ // - cli.ts: ⚠️ Partial (dynamic webpack config loading requires some `any`)
198
+ //
199
+ // Remaining overrides are for:
200
+ // 1. Code style/organization (not type safety)
201
+ // 2. Dynamic require() in cli.ts for webpack config loading
202
+ files: ["package/configExporter/**/*.ts"],
203
+ rules: {
204
+ // Code organization (functions before use due to large file)
205
+ "@typescript-eslint/no-use-before-define": "off",
206
+ // Import style (CommonJS require for dynamic imports)
207
+ "import/no-dynamic-require": "off",
208
+ // Class methods that are part of public API
209
+ "class-methods-use-this": "off",
210
+ // Template expressions (valid use cases with union types)
211
+ "@typescript-eslint/restrict-template-expressions": "off",
212
+ // Style preferences
213
+ "import/prefer-default-export": "off",
214
+ "no-underscore-dangle": "off",
215
+ "no-restricted-globals": "off",
216
+ "@typescript-eslint/no-unused-vars": "off",
217
+ "@typescript-eslint/require-await": "off"
218
+ }
219
+ },
220
+ {
221
+ // cli.ts: Dynamic webpack config loading requires `any` types
222
+ // This is acceptable as webpack configs can have any shape
223
+ files: ["package/configExporter/cli.ts"],
224
+ rules: {
225
+ "@typescript-eslint/no-explicit-any": "off",
226
+ "@typescript-eslint/no-unsafe-assignment": "off",
227
+ "@typescript-eslint/no-unsafe-member-access": "off",
228
+ "@typescript-eslint/no-unsafe-call": "off",
229
+ "@typescript-eslint/no-unsafe-return": "off"
230
+ }
231
+ },
232
+ {
233
+ // Remaining utils files that need type safety improvements
234
+ // These use dynamic requires and helper functions that return `any`
235
+ files: [
236
+ "package/utils/bundlerUtils.ts",
237
+ "package/utils/inliningCss.ts",
238
+ "package/utils/errorCodes.ts",
239
+ "package/utils/errorHelpers.ts",
240
+ "package/utils/pathValidation.ts",
241
+ "package/utils/getStyleRule.ts",
242
+ "package/utils/helpers.ts",
243
+ "package/utils/validateDependencies.ts",
244
+ "package/webpackDevServerConfig.ts"
245
+ ],
246
+ rules: {
247
+ "@typescript-eslint/no-unsafe-assignment": "off",
248
+ "@typescript-eslint/no-unsafe-member-access": "off",
249
+ "@typescript-eslint/no-unsafe-argument": "off",
250
+ "@typescript-eslint/no-unsafe-call": "off",
251
+ "@typescript-eslint/no-unsafe-return": "off",
252
+ "@typescript-eslint/no-explicit-any": "off",
253
+ "no-useless-escape": "off"
254
+ }
255
+ },
256
+ {
257
+ files: ["package/plugins/**/*.ts", "package/optimization/**/*.ts"],
258
+ rules: {
259
+ "@typescript-eslint/no-unsafe-assignment": "off",
260
+ "@typescript-eslint/no-unsafe-call": "off",
261
+ "@typescript-eslint/no-unsafe-member-access": "off",
262
+ "@typescript-eslint/no-redundant-type-constituents": "off",
263
+ "import/prefer-default-export": "off"
264
+ }
265
+ },
266
+ {
267
+ files: [
268
+ "package/index.ts",
269
+ "package/rspack/index.ts",
270
+ "package/rules/**/*.ts",
271
+ "package/swc/index.ts",
272
+ "package/esbuild/index.ts",
273
+ "package/dev_server.ts",
274
+ "package/env.ts"
275
+ ],
276
+ rules: {
277
+ "@typescript-eslint/no-unsafe-assignment": "off",
278
+ "@typescript-eslint/no-unsafe-call": "off",
279
+ "@typescript-eslint/no-unsafe-return": "off",
280
+ "@typescript-eslint/no-unsafe-member-access": "off",
281
+ "@typescript-eslint/no-unsafe-argument": "off",
282
+ "@typescript-eslint/no-redundant-type-constituents": "off",
283
+ "@typescript-eslint/no-unused-vars": "off",
284
+ "@typescript-eslint/no-unsafe-function-type": "off",
285
+ "import/prefer-default-export": "off",
286
+ "no-underscore-dangle": "off"
287
+ }
288
+ },
289
+ {
290
+ // package/environments/**/*.ts now passes no-unused-vars rule
291
+ // Type test functions use underscore prefix (argsIgnorePattern: "^_")
292
+ // All other variables are used in the code
293
+ files: ["package/environments/**/*.ts"],
294
+ rules: {
295
+ "@typescript-eslint/no-unsafe-assignment": "off",
296
+ "@typescript-eslint/no-unsafe-call": "off",
297
+ "@typescript-eslint/no-unsafe-return": "off",
298
+ "@typescript-eslint/no-unsafe-member-access": "off",
299
+ "@typescript-eslint/no-unsafe-argument": "off",
300
+ "@typescript-eslint/no-redundant-type-constituents": "off",
301
+ "@typescript-eslint/no-unsafe-function-type": "off",
302
+ "import/prefer-default-export": "off",
303
+ "no-underscore-dangle": "off"
304
+ }
305
+ },
306
+
307
+ // Prettier config must be last to override other configs
308
+ prettierConfig
309
+ ]
data/jest.config.js CHANGED
@@ -1,5 +1,12 @@
1
1
  module.exports = {
2
2
  roots: ["<rootDir>/test"],
3
3
  testPathIgnorePatterns: ["/__fixtures__/", "/__utils__/"],
4
- resolver: "<rootDir>/test/resolver"
4
+ resolver: "<rootDir>/test/resolver",
5
+ preset: "ts-jest",
6
+ testEnvironment: "node",
7
+ moduleFileExtensions: ["ts", "tsx", "js", "jsx", "json", "node"],
8
+ transform: {
9
+ "^.+\\.tsx?$": "ts-jest"
10
+ },
11
+ transformIgnorePatterns: ["node_modules/(?!(.*\\.mjs$))"]
5
12
  }
data/knip.ts ADDED
@@ -0,0 +1,61 @@
1
+ import type { KnipConfig } from "knip"
2
+
3
+ const config: KnipConfig = {
4
+ project: ["package/**/*.{ts,js}", "test/**/*.{ts,js}", "scripts/**/*.js"],
5
+ ignore: [
6
+ "package/**/*.d.ts",
7
+ "package/**/*.js",
8
+ "package/**/*.js.map",
9
+ "package/**/*.d.ts.map",
10
+ "test/fixtures/**",
11
+ "test/helpers.js", // Test utility file used by jest
12
+ "spec/**",
13
+ "gemfiles/**"
14
+ ],
15
+ ignoreBinaries: ["sed"],
16
+ ignoreDependencies: [
17
+ // These are peer dependencies that may not be directly imported
18
+ "@babel/core",
19
+ "@types/babel__core",
20
+ "@types/webpack",
21
+ "webpack-dev-server",
22
+ // Test/build tooling
23
+ "memory-fs",
24
+ "thenify",
25
+ // Used in type tests but not directly imported
26
+ "@rspack/plugin-react-refresh",
27
+ // CLI tools used by developers
28
+ "@rspack/cli",
29
+ "webpack-cli",
30
+ "husky",
31
+ // Optional dependencies used in webpack/rspack configs
32
+ "mini-css-extract-plugin",
33
+ "webpack-assets-manifest",
34
+ "webpack-subresource-integrity",
35
+ "rspack-manifest-plugin",
36
+ "sass-loader",
37
+ // Package merger utility
38
+ "@types/webpack-merge",
39
+ // Optional runtime dependencies
40
+ "ts-node",
41
+ "@pmmmwh/react-refresh-webpack-plugin",
42
+ // Optional peer dependencies referenced in code
43
+ "@rspack/core",
44
+ "@swc/core",
45
+ "babel-loader",
46
+ "compression-webpack-plugin",
47
+ "css-loader",
48
+ "esbuild-loader",
49
+ "swc-loader",
50
+ "webpack",
51
+ // eslint-config-airbnb isn't detected because it's used by compat.extends("airbnb"),
52
+ // the rest are its peerDependencies
53
+ "eslint-config-airbnb",
54
+ "eslint-plugin-import",
55
+ "eslint-plugin-jsx-a11y",
56
+ "eslint-plugin-react",
57
+ "eslint-plugin-react-hooks"
58
+ ]
59
+ }
60
+
61
+ export default config
@@ -1,13 +1,11 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  ENV["RAILS_ENV"] ||= "development"
4
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5
+ ENV["APP_ROOT"] ||= File.expand_path("..", __dir__)
5
6
 
6
7
  require "bundler/setup"
7
8
  require "shakapacker"
8
- require "shakapacker/webpack_runner"
9
+ require "shakapacker/runner"
9
10
 
10
- APP_ROOT = File.expand_path("..", __dir__)
11
- Dir.chdir(APP_ROOT) do
12
- Shakapacker::WebpackRunner.run(ARGV)
13
- end
11
+ Shakapacker::Runner.run(ARGV)
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Minimal shim - all logic is in the TypeScript module
4
+ const { run } = require("shakapacker/configExporter")
5
+
6
+ run(process.argv.slice(2))
7
+ .then((exitCode) => process.exit(exitCode))
8
+ .catch((error) => {
9
+ console.error(error.message)
10
+ process.exit(1)
11
+ })
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  ENV["RAILS_ENV"] ||= "development"
4
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile", __FILE__)
4
+ ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
5
5
 
6
6
  require "bundler/setup"
7
7
  require "shakapacker"