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.
- checksums.yaml +4 -4
- data/.eslintignore +1 -0
- data/.eslintrc.fast.js +40 -0
- data/.eslintrc.js +48 -0
- data/.github/STATUS.md +1 -0
- data/.github/workflows/claude-code-review.yml +54 -0
- data/.github/workflows/claude.yml +50 -0
- data/.github/workflows/dummy.yml +9 -4
- data/.github/workflows/generator.yml +32 -10
- data/.github/workflows/node.yml +23 -1
- data/.github/workflows/ruby.yml +33 -2
- data/.github/workflows/test-bundlers.yml +170 -0
- data/.gitignore +20 -0
- data/.husky/pre-commit +2 -0
- data/.npmignore +56 -0
- data/.prettierignore +3 -0
- data/.rubocop.yml +1 -0
- data/.yalcignore +26 -0
- data/CHANGELOG.md +302 -16
- data/CLAUDE.md +29 -0
- data/CONTRIBUTING.md +138 -20
- data/Gemfile.lock +83 -89
- data/README.md +343 -105
- data/Rakefile +39 -4
- data/TODO.md +50 -0
- data/TODO_v9.md +87 -0
- data/bin/export-bundler-config +11 -0
- data/conductor-setup.sh +70 -0
- data/conductor.json +7 -0
- data/docs/cdn_setup.md +379 -0
- data/docs/common-upgrades.md +615 -0
- data/docs/css-modules-export-mode.md +512 -0
- data/docs/deployment.md +62 -9
- data/docs/optional-peer-dependencies.md +198 -0
- data/docs/peer-dependencies.md +60 -0
- data/docs/react.md +6 -14
- data/docs/releasing.md +197 -0
- data/docs/rspack.md +190 -0
- data/docs/rspack_migration_guide.md +305 -0
- data/docs/subresource_integrity.md +54 -0
- data/docs/transpiler-migration.md +209 -0
- data/docs/transpiler-performance.md +179 -0
- data/docs/troubleshooting.md +157 -22
- data/docs/typescript-migration.md +379 -0
- data/docs/typescript.md +99 -0
- data/docs/using_esbuild_loader.md +3 -3
- data/docs/using_swc_loader.md +112 -10
- data/docs/v6_upgrade.md +10 -0
- data/docs/v8_upgrade.md +3 -5
- data/docs/v9_upgrade.md +458 -0
- data/gemfiles/Gemfile-rails.6.0.x +2 -1
- data/gemfiles/Gemfile-rails.6.1.x +1 -1
- data/gemfiles/Gemfile-rails.7.0.x +2 -2
- data/gemfiles/Gemfile-rails.7.1.x +1 -2
- data/gemfiles/Gemfile-rails.7.2.x +11 -0
- data/gemfiles/Gemfile-rails.8.0.x +11 -0
- data/lib/install/bin/export-bundler-config +11 -0
- data/lib/install/bin/shakapacker +4 -6
- data/lib/install/bin/shakapacker-dev-server +1 -1
- data/lib/install/config/rspack/rspack.config.js +6 -0
- data/lib/install/config/rspack/rspack.config.ts +7 -0
- data/lib/install/config/shakapacker.yml +25 -5
- data/lib/install/config/webpack/webpack.config.ts +7 -0
- data/lib/install/package.json +38 -0
- data/lib/install/template.rb +194 -44
- data/lib/shakapacker/bundler_switcher.rb +329 -0
- data/lib/shakapacker/compiler.rb +2 -1
- data/lib/shakapacker/compiler_strategy.rb +2 -2
- data/lib/shakapacker/configuration.rb +173 -2
- data/lib/shakapacker/dev_server_runner.rb +29 -8
- data/lib/shakapacker/digest_strategy.rb +2 -1
- data/lib/shakapacker/doctor.rb +905 -0
- data/lib/shakapacker/helper.rb +64 -16
- data/lib/shakapacker/manifest.rb +10 -3
- data/lib/shakapacker/mtime_strategy.rb +1 -1
- data/lib/shakapacker/railtie.rb +4 -4
- data/lib/shakapacker/rspack_runner.rb +19 -0
- data/lib/shakapacker/runner.rb +159 -10
- data/lib/shakapacker/swc_migrator.rb +384 -0
- data/lib/shakapacker/utils/manager.rb +15 -2
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker/version_checker.rb +2 -2
- data/lib/shakapacker/webpack_runner.rb +6 -43
- data/lib/shakapacker.rb +22 -11
- data/lib/tasks/shakapacker/doctor.rake +8 -0
- data/lib/tasks/shakapacker/export_bundler_config.rake +72 -0
- data/lib/tasks/shakapacker/install.rake +12 -2
- data/lib/tasks/shakapacker/migrate_to_swc.rake +13 -0
- data/lib/tasks/shakapacker/switch_bundler.rake +82 -0
- data/lib/tasks/shakapacker.rake +2 -0
- data/package/.npmignore +4 -0
- data/package/babel/preset.ts +56 -0
- data/package/config.ts +175 -0
- data/package/configExporter/cli.ts +683 -0
- data/package/configExporter/configDocs.ts +102 -0
- data/package/configExporter/fileWriter.ts +92 -0
- data/package/configExporter/index.ts +5 -0
- data/package/configExporter/types.ts +36 -0
- data/package/configExporter/yamlSerializer.ts +266 -0
- data/package/{dev_server.js → dev_server.ts} +8 -5
- data/package/env.ts +92 -0
- data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +30 -0
- data/package/environments/{base.js → base.ts} +56 -60
- data/package/environments/development.ts +90 -0
- data/package/environments/production.ts +80 -0
- data/package/environments/test.ts +53 -0
- data/package/environments/types.ts +98 -0
- data/package/esbuild/index.ts +42 -0
- data/package/index.d.ts +3 -60
- data/package/index.ts +55 -0
- data/package/loaders.d.ts +28 -0
- data/package/optimization/rspack.ts +36 -0
- data/package/optimization/webpack.ts +57 -0
- data/package/plugins/rspack.ts +103 -0
- data/package/plugins/webpack.ts +62 -0
- data/package/rspack/index.ts +64 -0
- data/package/rules/{babel.js → babel.ts} +2 -2
- data/package/rules/{coffee.js → coffee.ts} +1 -1
- data/package/rules/css.ts +3 -0
- data/package/rules/{erb.js → erb.ts} +1 -1
- data/package/rules/esbuild.ts +10 -0
- data/package/rules/file.ts +40 -0
- data/package/rules/{jscommon.js → jscommon.ts} +4 -4
- data/package/rules/{less.js → less.ts} +4 -4
- data/package/rules/raw.ts +25 -0
- data/package/rules/rspack.ts +176 -0
- data/package/rules/{sass.js → sass.ts} +7 -3
- data/package/rules/{stylus.js → stylus.ts} +4 -8
- data/package/rules/swc.ts +10 -0
- data/package/rules/webpack.ts +16 -0
- data/package/swc/index.ts +56 -0
- data/package/types/README.md +88 -0
- data/package/types/index.ts +61 -0
- data/package/types.ts +108 -0
- data/package/utils/configPath.ts +6 -0
- data/package/utils/debug.ts +49 -0
- data/package/utils/defaultConfigPath.ts +4 -0
- data/package/utils/errorCodes.ts +219 -0
- data/package/utils/errorHelpers.ts +143 -0
- data/package/utils/getStyleRule.ts +64 -0
- data/package/utils/helpers.ts +85 -0
- data/package/utils/{inliningCss.js → inliningCss.ts} +3 -3
- data/package/utils/pathValidation.ts +139 -0
- data/package/utils/requireOrError.ts +15 -0
- data/package/utils/snakeToCamelCase.ts +5 -0
- data/package/utils/typeGuards.ts +342 -0
- data/package/utils/validateDependencies.ts +61 -0
- data/package/webpack-types.d.ts +33 -0
- data/package/webpackDevServerConfig.ts +117 -0
- data/package-lock.json +13047 -0
- data/package.json +154 -18
- data/scripts/remove-use-strict.js +45 -0
- data/scripts/type-check-no-emit.js +27 -0
- data/test/helpers.js +1 -1
- data/test/package/config.test.js +43 -0
- data/test/package/env.test.js +42 -7
- data/test/package/environments/base.test.js +5 -1
- data/test/package/rules/babel.test.js +16 -0
- data/test/package/rules/esbuild.test.js +1 -1
- data/test/package/rules/raw.test.js +40 -7
- data/test/package/rules/swc.test.js +1 -1
- data/test/package/rules/webpack.test.js +35 -0
- data/test/package/staging.test.js +4 -3
- data/test/package/transpiler-defaults.test.js +127 -0
- data/test/peer-dependencies.sh +85 -0
- data/test/scripts/remove-use-strict.test.js +125 -0
- data/test/typescript/build.test.js +118 -0
- data/test/typescript/environments.test.js +107 -0
- data/test/typescript/pathValidation.test.js +142 -0
- data/test/typescript/securityValidation.test.js +182 -0
- data/tools/README.md +124 -0
- data/tools/css-modules-v9-codemod.js +179 -0
- data/tsconfig.eslint.json +16 -0
- data/tsconfig.json +38 -0
- data/yarn.lock +4165 -2706
- metadata +129 -41
- data/package/babel/preset.js +0 -37
- data/package/config.js +0 -54
- data/package/env.js +0 -48
- data/package/environments/development.js +0 -13
- data/package/environments/production.js +0 -88
- data/package/environments/test.js +0 -3
- data/package/esbuild/index.js +0 -40
- data/package/index.js +0 -40
- data/package/rules/css.js +0 -3
- data/package/rules/esbuild.js +0 -10
- data/package/rules/file.js +0 -29
- data/package/rules/index.js +0 -20
- data/package/rules/raw.js +0 -5
- data/package/rules/swc.js +0 -10
- data/package/swc/index.js +0 -50
- data/package/utils/configPath.js +0 -4
- data/package/utils/defaultConfigPath.js +0 -2
- data/package/utils/getStyleRule.js +0 -40
- data/package/utils/helpers.js +0 -58
- data/package/utils/snakeToCamelCase.js +0 -5
- data/package/webpackDevServerConfig.js +0 -71
- data/test/package/rules/index.test.js +0 -16
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shakapacker",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.2.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": {
|
|
@@ -14,65 +14,201 @@
|
|
|
14
14
|
"author": "David Heinemeier Hansson <david@basecamp.com>, Justin Gordon <justin@shakacode.com>",
|
|
15
15
|
"main": "package/index.js",
|
|
16
16
|
"types": "package/index.d.ts",
|
|
17
|
+
"exports": {
|
|
18
|
+
".": "./package/index.js",
|
|
19
|
+
"./types": "./package/types/index.js",
|
|
20
|
+
"./webpack": "./package/webpack/index.js",
|
|
21
|
+
"./rspack": "./package/rspack/index.js",
|
|
22
|
+
"./swc": "./package/swc/index.js",
|
|
23
|
+
"./esbuild": "./package/esbuild/index.js",
|
|
24
|
+
"./configExporter": "./package/configExporter/index.js",
|
|
25
|
+
"./package.json": "./package.json",
|
|
26
|
+
"./package/babel/preset.js": "./package/babel/preset.js",
|
|
27
|
+
"./package/*": "./package/*"
|
|
28
|
+
},
|
|
17
29
|
"files": [
|
|
18
30
|
"package",
|
|
19
31
|
"lib/install/config/shakapacker.yml"
|
|
20
32
|
],
|
|
21
33
|
"scripts": {
|
|
34
|
+
"clean:ts": "find package -name '*.ts' -not -name '*.d.ts' | sed 's/\\.ts$//' | xargs -I {} rm -f {}.js {}.d.ts {}.d.ts.map {}.js.map",
|
|
35
|
+
"build": "tsc && node scripts/remove-use-strict.js && yarn prettier --write 'package/**/*.js'",
|
|
36
|
+
"build:types": "tsc",
|
|
22
37
|
"lint": "eslint .",
|
|
23
|
-
"
|
|
38
|
+
"lint:fast": "eslint . --ext .js,.jsx,.ts,.tsx --config .eslintrc.fast.js",
|
|
39
|
+
"test": "jest",
|
|
40
|
+
"type-check": "tsc --noEmit",
|
|
41
|
+
"prepublishOnly": "yarn build && yarn type-check"
|
|
24
42
|
},
|
|
25
43
|
"dependencies": {
|
|
26
44
|
"js-yaml": "^4.1.0",
|
|
27
|
-
"path-complete-extname": "^1.0.0"
|
|
45
|
+
"path-complete-extname": "^1.0.0",
|
|
46
|
+
"webpack-merge": "^5.8.0"
|
|
28
47
|
},
|
|
29
48
|
"devDependencies": {
|
|
49
|
+
"@rspack/cli": "^1.4.11",
|
|
50
|
+
"@rspack/core": "^1.4.11",
|
|
51
|
+
"@swc/core": "^1.3.0",
|
|
52
|
+
"@types/babel__core": "^7.20.5",
|
|
53
|
+
"@types/js-yaml": "^4.0.9",
|
|
54
|
+
"@types/node": "^24.5.2",
|
|
55
|
+
"@types/path-complete-extname": "^1.0.3",
|
|
56
|
+
"@types/webpack": "^5.28.5",
|
|
57
|
+
"@types/webpack-dev-server": "^4.7.2",
|
|
58
|
+
"@types/webpack-merge": "^5.0.0",
|
|
59
|
+
"@typescript-eslint/eslint-plugin": "^8.45.0",
|
|
60
|
+
"@typescript-eslint/parser": "^8.45.0",
|
|
30
61
|
"babel-loader": "^8.2.4",
|
|
31
62
|
"compression-webpack-plugin": "^9.0.0",
|
|
63
|
+
"css-loader": "^7.1.2",
|
|
32
64
|
"esbuild-loader": "^2.18.0",
|
|
33
65
|
"eslint": "^8.0.0",
|
|
34
|
-
"eslint-config-airbnb": "^19.0.
|
|
66
|
+
"eslint-config-airbnb": "^19.0.4",
|
|
35
67
|
"eslint-config-prettier": "^9.0.0",
|
|
36
|
-
"eslint-plugin-import": "^2.
|
|
68
|
+
"eslint-plugin-import": "^2.31.0",
|
|
37
69
|
"eslint-plugin-jest": "^27.9.0",
|
|
38
|
-
"eslint-plugin-jsx-a11y": "^6.
|
|
39
|
-
"eslint-plugin-prettier": "^5.
|
|
40
|
-
"eslint-plugin-react": "^7.
|
|
70
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
71
|
+
"eslint-plugin-prettier": "^5.2.6",
|
|
72
|
+
"eslint-plugin-react": "^7.37.5",
|
|
41
73
|
"eslint-plugin-react-hooks": "^4.6.0",
|
|
42
|
-
"
|
|
74
|
+
"husky": "^9.1.7",
|
|
75
|
+
"jest": "^29.7.0",
|
|
76
|
+
"lint-staged": "^15.2.10",
|
|
43
77
|
"memory-fs": "^0.5.0",
|
|
78
|
+
"mini-css-extract-plugin": "^2.9.4",
|
|
44
79
|
"prettier": "^3.2.5",
|
|
80
|
+
"rspack-manifest-plugin": "^5.0.3",
|
|
81
|
+
"sass-loader": "^16.0.5",
|
|
45
82
|
"swc-loader": "^0.1.15",
|
|
46
83
|
"thenify": "^3.3.1",
|
|
47
|
-
"
|
|
84
|
+
"typescript": "^5.9.2",
|
|
85
|
+
"webpack": "5.93.0",
|
|
48
86
|
"webpack-assets-manifest": "^5.0.6",
|
|
49
|
-
"webpack-
|
|
87
|
+
"webpack-subresource-integrity": "^5.1.0"
|
|
50
88
|
},
|
|
51
89
|
"peerDependencies": {
|
|
52
90
|
"@babel/core": "^7.17.9",
|
|
53
91
|
"@babel/plugin-transform-runtime": "^7.17.0",
|
|
54
92
|
"@babel/preset-env": "^7.16.11",
|
|
55
93
|
"@babel/runtime": "^7.17.9",
|
|
94
|
+
"@rspack/cli": "^1.0.0",
|
|
95
|
+
"@rspack/core": "^1.0.0",
|
|
96
|
+
"@rspack/plugin-react-refresh": "^1.0.0",
|
|
97
|
+
"@swc/core": "^1.3.0",
|
|
56
98
|
"@types/babel__core": "^7.0.0",
|
|
57
99
|
"@types/webpack": "^5.0.0",
|
|
58
|
-
"babel-loader": "^8.2.4 || ^9.0.0",
|
|
59
|
-
"compression-webpack-plugin": "^9.0.0 || ^10.0.0|| ^11.0.0",
|
|
100
|
+
"babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0",
|
|
101
|
+
"compression-webpack-plugin": "^9.0.0 || ^10.0.0 || ^11.0.0",
|
|
102
|
+
"css-loader": "^6.8.1 || ^7.0.0",
|
|
103
|
+
"esbuild": "^0.14.0 || ^0.15.0 || ^0.16.0 || ^0.17.0 || ^0.18.0 || ^0.19.0 || ^0.20.0 || ^0.21.0 || ^0.22.0 || ^0.23.0 || ^0.24.0",
|
|
104
|
+
"esbuild-loader": "^2.0.0 || ^3.0.0 || ^4.0.0",
|
|
105
|
+
"mini-css-extract-plugin": "^2.0.0",
|
|
106
|
+
"rspack-manifest-plugin": "^5.0.0",
|
|
107
|
+
"sass": "^1.50.0",
|
|
108
|
+
"sass-loader": "^13.0.0 || ^14.0.0 || ^15.0.0 || ^16.0.0",
|
|
109
|
+
"swc-loader": "^0.1.15 || ^0.2.0",
|
|
60
110
|
"terser-webpack-plugin": "^5.3.1",
|
|
61
|
-
"webpack": "^5.
|
|
62
|
-
"webpack-assets-manifest": "^5.0.6",
|
|
63
|
-
"webpack-cli": "^4.9.2 || ^5.0.0",
|
|
64
|
-
"webpack-dev-server": "^4.
|
|
65
|
-
"webpack-
|
|
111
|
+
"webpack": "^5.76.0",
|
|
112
|
+
"webpack-assets-manifest": "^5.0.6 || ^6.0.0",
|
|
113
|
+
"webpack-cli": "^4.9.2 || ^5.0.0 || ^6.0.0",
|
|
114
|
+
"webpack-dev-server": "^4.15.2 || ^5.2.2",
|
|
115
|
+
"webpack-subresource-integrity": "^5.1.0"
|
|
66
116
|
},
|
|
67
117
|
"peerDependenciesMeta": {
|
|
118
|
+
"@babel/core": {
|
|
119
|
+
"optional": true
|
|
120
|
+
},
|
|
121
|
+
"@babel/plugin-transform-runtime": {
|
|
122
|
+
"optional": true
|
|
123
|
+
},
|
|
124
|
+
"@babel/preset-env": {
|
|
125
|
+
"optional": true
|
|
126
|
+
},
|
|
127
|
+
"@babel/runtime": {
|
|
128
|
+
"optional": true
|
|
129
|
+
},
|
|
130
|
+
"@rspack/core": {
|
|
131
|
+
"optional": true
|
|
132
|
+
},
|
|
133
|
+
"@rspack/cli": {
|
|
134
|
+
"optional": true
|
|
135
|
+
},
|
|
136
|
+
"@rspack/plugin-react-refresh": {
|
|
137
|
+
"optional": true
|
|
138
|
+
},
|
|
139
|
+
"@swc/core": {
|
|
140
|
+
"optional": true
|
|
141
|
+
},
|
|
68
142
|
"@types/babel__core": {
|
|
69
143
|
"optional": true
|
|
70
144
|
},
|
|
71
145
|
"@types/webpack": {
|
|
72
146
|
"optional": true
|
|
147
|
+
},
|
|
148
|
+
"babel-loader": {
|
|
149
|
+
"optional": true
|
|
150
|
+
},
|
|
151
|
+
"compression-webpack-plugin": {
|
|
152
|
+
"optional": true
|
|
153
|
+
},
|
|
154
|
+
"css-loader": {
|
|
155
|
+
"optional": true
|
|
156
|
+
},
|
|
157
|
+
"esbuild": {
|
|
158
|
+
"optional": true
|
|
159
|
+
},
|
|
160
|
+
"esbuild-loader": {
|
|
161
|
+
"optional": true
|
|
162
|
+
},
|
|
163
|
+
"mini-css-extract-plugin": {
|
|
164
|
+
"optional": true
|
|
165
|
+
},
|
|
166
|
+
"rspack-manifest-plugin": {
|
|
167
|
+
"optional": true
|
|
168
|
+
},
|
|
169
|
+
"sass": {
|
|
170
|
+
"optional": true
|
|
171
|
+
},
|
|
172
|
+
"sass-loader": {
|
|
173
|
+
"optional": true
|
|
174
|
+
},
|
|
175
|
+
"swc-loader": {
|
|
176
|
+
"optional": true
|
|
177
|
+
},
|
|
178
|
+
"terser-webpack-plugin": {
|
|
179
|
+
"optional": true
|
|
180
|
+
},
|
|
181
|
+
"webpack": {
|
|
182
|
+
"optional": true
|
|
183
|
+
},
|
|
184
|
+
"webpack-assets-manifest": {
|
|
185
|
+
"optional": true
|
|
186
|
+
},
|
|
187
|
+
"webpack-cli": {
|
|
188
|
+
"optional": true
|
|
189
|
+
},
|
|
190
|
+
"webpack-dev-server": {
|
|
191
|
+
"optional": true
|
|
192
|
+
},
|
|
193
|
+
"webpack-subresource-integrity": {
|
|
194
|
+
"optional": true
|
|
73
195
|
}
|
|
74
196
|
},
|
|
75
197
|
"packageManager": "yarn@1.22.22",
|
|
198
|
+
"lint-staged": {
|
|
199
|
+
"*.{js,jsx}": [
|
|
200
|
+
"eslint --fix",
|
|
201
|
+
"prettier --write"
|
|
202
|
+
],
|
|
203
|
+
"*.{ts,tsx}": [
|
|
204
|
+
"eslint --fix",
|
|
205
|
+
"prettier --write",
|
|
206
|
+
"node scripts/type-check-no-emit.js"
|
|
207
|
+
],
|
|
208
|
+
"*.{json,yml,yaml,md}": [
|
|
209
|
+
"prettier --write"
|
|
210
|
+
]
|
|
211
|
+
},
|
|
76
212
|
"engines": {
|
|
77
213
|
"node": ">= 14",
|
|
78
214
|
"yarn": ">=1 <5"
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require("fs")
|
|
3
|
+
const path = require("path")
|
|
4
|
+
|
|
5
|
+
// Recursively find all .js files in a directory
|
|
6
|
+
function findJsFiles(dir) {
|
|
7
|
+
const files = []
|
|
8
|
+
const items = fs.readdirSync(dir, { withFileTypes: true })
|
|
9
|
+
|
|
10
|
+
items.forEach((item) => {
|
|
11
|
+
const fullPath = path.join(dir, item.name)
|
|
12
|
+
if (item.isDirectory()) {
|
|
13
|
+
files.push(...findJsFiles(fullPath))
|
|
14
|
+
} else if (item.isFile() && item.name.endsWith(".js")) {
|
|
15
|
+
files.push(fullPath)
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
return files
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// Find all .js files in package directory
|
|
23
|
+
const files = findJsFiles("package")
|
|
24
|
+
|
|
25
|
+
files.forEach((file) => {
|
|
26
|
+
let content = fs.readFileSync(file, "utf8")
|
|
27
|
+
|
|
28
|
+
// Remove "use strict" directive with various quote styles and formatting
|
|
29
|
+
// Handles: optional whitespace, single/double/unicode quotes, optional semicolon,
|
|
30
|
+
// and any trailing whitespace/newline sequences
|
|
31
|
+
content = content.replace(
|
|
32
|
+
/^\s*["'\u2018\u2019\u201C\u201D]use\s+strict["'\u2018\u2019\u201C\u201D]\s*;?\s*[\r\n]*/,
|
|
33
|
+
""
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
// Ensure file ends with exactly one newline
|
|
37
|
+
if (!content.endsWith("\n")) {
|
|
38
|
+
content += "\n"
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
fs.writeFileSync(file, content, "utf8")
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
// eslint-disable-next-line no-console
|
|
45
|
+
console.log(`Removed "use strict" from ${files.length} files`)
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type-check script for lint-staged
|
|
5
|
+
*
|
|
6
|
+
* This script runs TypeScript type checking without emitting files.
|
|
7
|
+
* It ignores any arguments passed by lint-staged to ensure tsc uses
|
|
8
|
+
* the project's tsconfig.json rather than trying to compile individual files.
|
|
9
|
+
*
|
|
10
|
+
* Without this wrapper, lint-staged would pass staged file paths as arguments
|
|
11
|
+
* to tsc, causing it to ignore tsconfig.json and fail type checking.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
const { execSync } = require("child_process")
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
// Run tsc with no arguments (ignoring any passed by lint-staged)
|
|
18
|
+
// This ensures it uses tsconfig.json properly
|
|
19
|
+
execSync("npx tsc --noEmit", {
|
|
20
|
+
stdio: "inherit",
|
|
21
|
+
cwd: process.cwd()
|
|
22
|
+
})
|
|
23
|
+
process.exit(0)
|
|
24
|
+
} catch (error) {
|
|
25
|
+
// Type checking failed
|
|
26
|
+
process.exit(1)
|
|
27
|
+
}
|
data/test/helpers.js
CHANGED
data/test/package/config.test.js
CHANGED
|
@@ -54,4 +54,47 @@ describe("Config", () => {
|
|
|
54
54
|
resolve("app/javascript/manifest.json")
|
|
55
55
|
)
|
|
56
56
|
})
|
|
57
|
+
|
|
58
|
+
test("should have integrity disabled by default", () => {
|
|
59
|
+
const config = require("../../package/config")
|
|
60
|
+
expect(config.integrity.enabled).toBe(false)
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test("should have sha384 as default hash function", () => {
|
|
64
|
+
const config = require("../../package/config")
|
|
65
|
+
expect(config.integrity.hash_functions).toStrictEqual(["sha384"])
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
test("should have anonymous as default crossorigin", () => {
|
|
69
|
+
const config = require("../../package/config")
|
|
70
|
+
expect(config.integrity.cross_origin).toBe("anonymous")
|
|
71
|
+
})
|
|
72
|
+
|
|
73
|
+
test("should allow enabling integrity", () => {
|
|
74
|
+
process.env.RAILS_ENV = "production"
|
|
75
|
+
process.env.SHAKAPACKER_CONFIG = "config/shakapacker_integrity.yml"
|
|
76
|
+
const config = require("../../package/config")
|
|
77
|
+
|
|
78
|
+
expect(config.integrity.enabled).toBe(true)
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
test("should allow configuring hash functions", () => {
|
|
82
|
+
process.env.RAILS_ENV = "production"
|
|
83
|
+
process.env.SHAKAPACKER_CONFIG = "config/shakapacker_integrity.yml"
|
|
84
|
+
const config = require("../../package/config")
|
|
85
|
+
|
|
86
|
+
expect(config.integrity.hash_functions).toStrictEqual([
|
|
87
|
+
"sha384",
|
|
88
|
+
"sha256",
|
|
89
|
+
"sha512"
|
|
90
|
+
])
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
test("should allow configuring crossorigin", () => {
|
|
94
|
+
process.env.RAILS_ENV = "production"
|
|
95
|
+
process.env.SHAKAPACKER_CONFIG = "config/shakapacker_integrity.yml"
|
|
96
|
+
const config = require("../../package/config")
|
|
97
|
+
|
|
98
|
+
expect(config.integrity.cross_origin).toBe("use-credentials")
|
|
99
|
+
})
|
|
57
100
|
})
|
data/test/package/env.test.js
CHANGED
|
@@ -24,6 +24,18 @@ describe("Env", () => {
|
|
|
24
24
|
delete process.env.NODE_ENV
|
|
25
25
|
expect(require("../../package/env")).toStrictEqual({
|
|
26
26
|
railsEnv: "development",
|
|
27
|
+
nodeEnv: "development",
|
|
28
|
+
isProduction: false,
|
|
29
|
+
isDevelopment: true,
|
|
30
|
+
runningWebpackDevServer: false
|
|
31
|
+
})
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
test("with undefined NODE_ENV and RAILS_ENV set to production", () => {
|
|
35
|
+
process.env.RAILS_ENV = "production"
|
|
36
|
+
delete process.env.NODE_ENV
|
|
37
|
+
expect(require("../../package/env")).toStrictEqual({
|
|
38
|
+
railsEnv: "production",
|
|
27
39
|
nodeEnv: "production",
|
|
28
40
|
isProduction: true,
|
|
29
41
|
isDevelopment: false,
|
|
@@ -35,10 +47,10 @@ describe("Env", () => {
|
|
|
35
47
|
delete process.env.NODE_ENV
|
|
36
48
|
delete process.env.RAILS_ENV
|
|
37
49
|
expect(require("../../package/env")).toStrictEqual({
|
|
38
|
-
railsEnv: "
|
|
39
|
-
nodeEnv: "
|
|
40
|
-
isProduction:
|
|
41
|
-
isDevelopment:
|
|
50
|
+
railsEnv: "development",
|
|
51
|
+
nodeEnv: "development",
|
|
52
|
+
isProduction: false,
|
|
53
|
+
isDevelopment: true,
|
|
42
54
|
runningWebpackDevServer: false
|
|
43
55
|
})
|
|
44
56
|
})
|
|
@@ -48,10 +60,33 @@ describe("Env", () => {
|
|
|
48
60
|
process.env.NODE_ENV = "staging"
|
|
49
61
|
expect(require("../../package/env")).toStrictEqual({
|
|
50
62
|
railsEnv: "staging",
|
|
51
|
-
nodeEnv: "
|
|
52
|
-
isProduction:
|
|
53
|
-
isDevelopment:
|
|
63
|
+
nodeEnv: "development",
|
|
64
|
+
isProduction: false,
|
|
65
|
+
isDevelopment: true,
|
|
66
|
+
runningWebpackDevServer: false
|
|
67
|
+
})
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
test("rejects malicious NODE_ENV values and uses default", () => {
|
|
71
|
+
process.env.RAILS_ENV = "development"
|
|
72
|
+
process.env.NODE_ENV = "../../../etc/passwd"
|
|
73
|
+
expect(require("../../package/env")).toStrictEqual({
|
|
74
|
+
railsEnv: "development",
|
|
75
|
+
nodeEnv: "development",
|
|
76
|
+
isProduction: false,
|
|
77
|
+
isDevelopment: true,
|
|
54
78
|
runningWebpackDevServer: false
|
|
55
79
|
})
|
|
56
80
|
})
|
|
81
|
+
|
|
82
|
+
test("warns when NODE_ENV is invalid", () => {
|
|
83
|
+
const consoleSpy = jest.spyOn(console, "warn").mockImplementation()
|
|
84
|
+
process.env.NODE_ENV = "invalid"
|
|
85
|
+
delete process.env.RAILS_ENV
|
|
86
|
+
require("../../package/env")
|
|
87
|
+
expect(consoleSpy).toHaveBeenCalledWith(
|
|
88
|
+
expect.stringContaining("Invalid NODE_ENV value: invalid")
|
|
89
|
+
)
|
|
90
|
+
consoleSpy.mockRestore()
|
|
91
|
+
})
|
|
57
92
|
})
|
|
@@ -7,6 +7,10 @@ const { chdirTestApp, resetEnv } = require("../../helpers")
|
|
|
7
7
|
const rootPath = process.cwd()
|
|
8
8
|
chdirTestApp()
|
|
9
9
|
|
|
10
|
+
// Set NODE_ENV before requiring modules to ensure contenthash is enabled
|
|
11
|
+
// Base config tests expect production-like behavior with contenthash
|
|
12
|
+
process.env.NODE_ENV = "production"
|
|
13
|
+
|
|
10
14
|
const baseConfig = require("../../../package/environments/base")
|
|
11
15
|
const config = require("../../../package/config")
|
|
12
16
|
|
|
@@ -79,7 +83,7 @@ describe("Base config", () => {
|
|
|
79
83
|
})
|
|
80
84
|
|
|
81
85
|
test("should return default loader rules for each file in config/loaders", () => {
|
|
82
|
-
const rules = require("../../../package/rules")
|
|
86
|
+
const rules = require("../../../package/rules/webpack")
|
|
83
87
|
|
|
84
88
|
const defaultRules = Object.keys(rules)
|
|
85
89
|
const configRules = baseConfig.module.rules
|
|
@@ -11,6 +11,7 @@ jest.mock("../../../package/config", () => {
|
|
|
11
11
|
const original = jest.requireActual("../../../package/config")
|
|
12
12
|
return {
|
|
13
13
|
...original,
|
|
14
|
+
javascript_transpiler: "babel", // Force babel for this test
|
|
14
15
|
additional_paths: [...original.additional_paths, "node_modules/included"]
|
|
15
16
|
}
|
|
16
17
|
})
|
|
@@ -32,6 +33,21 @@ const createWebpackConfig = (file, use) => ({
|
|
|
32
33
|
})
|
|
33
34
|
|
|
34
35
|
describe("babel", () => {
|
|
36
|
+
// Mock validateBabelDependencies to avoid actual dependency checking in tests
|
|
37
|
+
beforeAll(() => {
|
|
38
|
+
jest.mock("../../../package/utils/helpers", () => {
|
|
39
|
+
const original = jest.requireActual("../../../package/utils/helpers")
|
|
40
|
+
return {
|
|
41
|
+
...original,
|
|
42
|
+
validateBabelDependencies: jest.fn() // Mock to do nothing
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
afterAll(() => {
|
|
48
|
+
jest.unmock("../../../package/utils/helpers")
|
|
49
|
+
})
|
|
50
|
+
|
|
35
51
|
test("process source path", async () => {
|
|
36
52
|
const normalPath = `${pathToAppJavascript}/a.js`
|
|
37
53
|
const [tracked, loader] = createTrackLoader()
|
|
@@ -11,7 +11,7 @@ jest.mock("../../../package/config", () => {
|
|
|
11
11
|
const original = jest.requireActual("../../../package/config")
|
|
12
12
|
return {
|
|
13
13
|
...original,
|
|
14
|
-
|
|
14
|
+
javascript_transpiler: "esbuild",
|
|
15
15
|
additional_paths: [...original.additional_paths, "node_modules/included"]
|
|
16
16
|
}
|
|
17
17
|
})
|
|
@@ -1,12 +1,45 @@
|
|
|
1
|
-
const raw = require("../../../package/rules/raw")
|
|
2
|
-
|
|
3
1
|
describe("raw", () => {
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
describe("rspack bundler", () => {
|
|
3
|
+
beforeEach(() => {
|
|
4
|
+
jest.resetModules()
|
|
5
|
+
jest.doMock("../../../package/config", () => ({
|
|
6
|
+
assets_bundler: "rspack"
|
|
7
|
+
}))
|
|
8
|
+
})
|
|
9
|
+
|
|
10
|
+
afterEach(() => {
|
|
11
|
+
jest.dontMock("../../../package/config")
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
test("uses resourceQuery for any file with ?raw", () => {
|
|
15
|
+
const raw = require("../../../package/rules/raw")
|
|
16
|
+
expect(raw.resourceQuery).toStrictEqual(/raw/)
|
|
17
|
+
expect(raw.type).toBe("asset/source")
|
|
18
|
+
})
|
|
6
19
|
})
|
|
7
20
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
21
|
+
describe("webpack bundler", () => {
|
|
22
|
+
beforeEach(() => {
|
|
23
|
+
jest.resetModules()
|
|
24
|
+
jest.doMock("../../../package/config", () => ({
|
|
25
|
+
assets_bundler: "webpack"
|
|
26
|
+
}))
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
afterEach(() => {
|
|
30
|
+
jest.dontMock("../../../package/config")
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
test("supports ?raw query and .html fallback with oneOf", () => {
|
|
34
|
+
const raw = require("../../../package/rules/raw")
|
|
35
|
+
expect(raw.oneOf).toHaveLength(2)
|
|
36
|
+
// First rule: any file with ?raw
|
|
37
|
+
expect(raw.oneOf[0].resourceQuery).toStrictEqual(/raw/)
|
|
38
|
+
expect(raw.oneOf[0].type).toBe("asset/source")
|
|
39
|
+
// Second rule: .html files without query
|
|
40
|
+
expect(raw.oneOf[1].test.test(".html")).toBe(true)
|
|
41
|
+
expect(raw.oneOf[1].exclude.test(".js")).toBe(true)
|
|
42
|
+
expect(raw.oneOf[1].type).toBe("asset/source")
|
|
43
|
+
})
|
|
11
44
|
})
|
|
12
45
|
})
|
|
@@ -11,7 +11,7 @@ jest.mock("../../../package/config", () => {
|
|
|
11
11
|
const original = jest.requireActual("../../../package/config")
|
|
12
12
|
return {
|
|
13
13
|
...original,
|
|
14
|
-
|
|
14
|
+
javascript_transpiler: "swc",
|
|
15
15
|
additional_paths: [...original.additional_paths, "node_modules/included"]
|
|
16
16
|
}
|
|
17
17
|
})
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
const rules = require("../../../package/rules/webpack")
|
|
2
|
+
|
|
3
|
+
jest.mock("../../../package/utils/helpers", () => {
|
|
4
|
+
const original = jest.requireActual("../../../package/utils/helpers")
|
|
5
|
+
const moduleExists = () => false
|
|
6
|
+
return {
|
|
7
|
+
...original,
|
|
8
|
+
moduleExists
|
|
9
|
+
}
|
|
10
|
+
})
|
|
11
|
+
|
|
12
|
+
describe("index", () => {
|
|
13
|
+
test("rule tests are regexes or oneOf arrays", () => {
|
|
14
|
+
const rulesWithTest = rules.filter((rule) => !rule.oneOf)
|
|
15
|
+
const rulesWithOneOf = rules.filter((rule) => rule.oneOf)
|
|
16
|
+
|
|
17
|
+
// Verify all non-oneOf rules have test property
|
|
18
|
+
rulesWithTest.forEach((rule) => {
|
|
19
|
+
expect(rule.test).toBeInstanceOf(RegExp)
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
// Verify all oneOf rules are properly structured
|
|
23
|
+
rulesWithOneOf.forEach((rule) => {
|
|
24
|
+
expect(Array.isArray(rule.oneOf)).toBe(true)
|
|
25
|
+
rule.oneOf.forEach((subRule) => {
|
|
26
|
+
// Each subRule must have either a test or resourceQuery property (RegExp)
|
|
27
|
+
const matchers = [
|
|
28
|
+
subRule.test instanceof RegExp,
|
|
29
|
+
subRule.resourceQuery instanceof RegExp
|
|
30
|
+
]
|
|
31
|
+
expect(matchers.some(Boolean)).toBe(true)
|
|
32
|
+
})
|
|
33
|
+
})
|
|
34
|
+
})
|
|
35
|
+
})
|
|
@@ -19,7 +19,7 @@ describe("Custom environment", () => {
|
|
|
19
19
|
describe("generateWebpackConfig", () => {
|
|
20
20
|
beforeEach(() => jest.resetModules())
|
|
21
21
|
|
|
22
|
-
test("should use staging config and default
|
|
22
|
+
test("should use staging config and default development environment", () => {
|
|
23
23
|
process.env.RAILS_ENV = "staging"
|
|
24
24
|
delete process.env.NODE_ENV
|
|
25
25
|
|
|
@@ -31,9 +31,10 @@ describe("Custom environment", () => {
|
|
|
31
31
|
resolve("public", "packs-staging")
|
|
32
32
|
)
|
|
33
33
|
expect(webpackConfig.output.publicPath).toBe("/packs-staging/")
|
|
34
|
+
// With the NODE_ENV fix, staging now defaults to development environment
|
|
35
|
+
// instead of production, providing better DX for staging environments
|
|
34
36
|
expect(webpackConfig).toMatchObject({
|
|
35
|
-
devtool: "source-map"
|
|
36
|
-
stats: "normal"
|
|
37
|
+
devtool: "cheap-module-source-map"
|
|
37
38
|
})
|
|
38
39
|
})
|
|
39
40
|
})
|