shakapacker 9.3.0.beta.7 → 9.3.1
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/.claude/commands/update-changelog.md +224 -0
- data/.github/actionlint-matcher.json +17 -0
- data/.github/workflows/dummy.yml +9 -0
- data/.github/workflows/generator.yml +13 -0
- data/.github/workflows/node.yml +83 -0
- data/.github/workflows/ruby.yml +11 -0
- data/.github/workflows/test-bundlers.yml +10 -0
- data/CHANGELOG.md +55 -111
- data/CLAUDE.md +6 -10
- data/CONTRIBUTING.md +57 -0
- data/Gemfile.lock +1 -1
- data/README.md +84 -8
- data/docs/api-reference.md +519 -0
- data/docs/configuration.md +38 -4
- data/docs/css-modules-export-mode.md +40 -6
- data/docs/rspack_migration_guide.md +238 -2
- data/docs/transpiler-migration.md +12 -9
- data/docs/troubleshooting.md +21 -21
- data/docs/using_swc_loader.md +13 -10
- data/docs/v9_upgrade.md +11 -2
- data/eslint.config.fast.js +128 -8
- data/eslint.config.js +89 -33
- data/knip.ts +8 -1
- data/lib/install/config/shakapacker.yml +20 -7
- data/lib/shakapacker/configuration.rb +274 -8
- data/lib/shakapacker/dev_server.rb +88 -1
- data/lib/shakapacker/dev_server_runner.rb +4 -0
- data/lib/shakapacker/doctor.rb +5 -5
- data/lib/shakapacker/instance.rb +85 -1
- data/lib/shakapacker/manifest.rb +85 -11
- data/lib/shakapacker/version.rb +1 -1
- data/lib/shakapacker.rb +143 -3
- data/lib/tasks/shakapacker/doctor.rake +1 -1
- data/lib/tasks/shakapacker/export_bundler_config.rake +4 -4
- data/package/config.ts +2 -4
- data/package/configExporter/buildValidator.ts +53 -29
- data/package/configExporter/cli.ts +106 -76
- data/package/configExporter/configFile.ts +33 -26
- data/package/configExporter/types.ts +64 -0
- data/package/configExporter/yamlSerializer.ts +118 -43
- data/package/dev_server.ts +3 -2
- data/package/env.ts +2 -2
- data/package/environments/__type-tests__/rspack-plugin-compatibility.ts +6 -6
- data/package/environments/base.ts +6 -6
- data/package/environments/development.ts +7 -9
- data/package/environments/production.ts +7 -8
- data/package/environments/test.ts +4 -2
- data/package/esbuild/index.ts +0 -2
- data/package/index.d.ts +1 -0
- data/package/index.d.ts.template +1 -0
- data/package/index.ts +28 -5
- data/package/loaders.d.ts +2 -2
- data/package/optimization/webpack.ts +29 -31
- data/package/plugins/rspack.ts +3 -1
- data/package/plugins/webpack.ts +5 -3
- data/package/rspack/index.ts +5 -4
- data/package/rules/file.ts +2 -1
- data/package/rules/jscommon.ts +1 -0
- data/package/rules/raw.ts +3 -1
- data/package/rules/rspack.ts +0 -2
- data/package/rules/sass.ts +0 -2
- data/package/rules/webpack.ts +0 -1
- data/package/swc/index.ts +0 -2
- data/package/types.ts +8 -11
- data/package/utils/debug.ts +0 -4
- data/package/utils/getStyleRule.ts +17 -9
- data/package/utils/helpers.ts +8 -4
- data/package/utils/pathValidation.ts +78 -18
- data/package/utils/requireOrError.ts +14 -5
- data/package/utils/typeGuards.ts +43 -46
- data/package/webpack-types.d.ts +2 -2
- data/package/webpackDevServerConfig.ts +5 -4
- data/package.json +2 -3
- data/test/package/configExporter/cli.test.js +440 -0
- data/test/package/configExporter/types.test.js +163 -0
- data/test/package/configExporter.test.js +264 -0
- data/test/package/transpiler-defaults.test.js +42 -0
- data/test/package/yamlSerializer.test.js +204 -0
- data/test/typescript/pathValidation.test.js +44 -0
- data/test/typescript/requireOrError.test.js +49 -0
- data/yarn.lock +0 -32
- metadata +14 -5
- data/.eslintrc.fast.js +0 -40
- data/.eslintrc.js +0 -84
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
/* eslint global-require: 0 */
|
|
2
1
|
/* eslint import/no-dynamic-require: 0 */
|
|
3
|
-
|
|
2
|
+
import type { Config } from "../types"
|
|
4
3
|
|
|
5
|
-
const
|
|
4
|
+
const config = require("../config") as Config
|
|
5
|
+
|
|
6
|
+
interface ErrorWithCause extends Error {
|
|
7
|
+
cause?: unknown
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const requireOrError = (moduleName: string): unknown => {
|
|
6
11
|
try {
|
|
7
12
|
return require(moduleName)
|
|
8
|
-
} catch (
|
|
9
|
-
|
|
13
|
+
} catch (originalError: unknown) {
|
|
14
|
+
const error: ErrorWithCause = new Error(
|
|
10
15
|
`[SHAKAPACKER]: ${moduleName} is required for ${config.assets_bundler} but is not installed. View Shakapacker's documented dependencies at https://github.com/shakacode/shakapacker/tree/main/docs/peer-dependencies.md`
|
|
11
16
|
)
|
|
17
|
+
// Add the original error as the cause for better debugging (ES2022+)
|
|
18
|
+
// Using custom interface since target is ES2020 but runtime supports it
|
|
19
|
+
error.cause = originalError
|
|
20
|
+
throw error
|
|
12
21
|
}
|
|
13
22
|
}
|
|
14
23
|
|
data/package/utils/typeGuards.ts
CHANGED
|
@@ -66,6 +66,38 @@ export function clearValidationCache(): void {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
/**
|
|
70
|
+
* Type guard to validate DevServerConfig object at runtime
|
|
71
|
+
* In production, performs minimal validation for performance
|
|
72
|
+
*/
|
|
73
|
+
export function isValidDevServerConfig(obj: unknown): obj is DevServerConfig {
|
|
74
|
+
if (typeof obj !== "object" || obj === null) {
|
|
75
|
+
return false
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// In production, skip deep validation unless explicitly enabled
|
|
79
|
+
if (!shouldValidate()) {
|
|
80
|
+
return true
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const config = obj as Record<string, unknown>
|
|
84
|
+
|
|
85
|
+
// All fields are optional, just check types if present
|
|
86
|
+
if (
|
|
87
|
+
config.hmr !== undefined &&
|
|
88
|
+
typeof config.hmr !== "boolean" &&
|
|
89
|
+
config.hmr !== "only"
|
|
90
|
+
) {
|
|
91
|
+
return false
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (config.port !== undefined && !validatePort(config.port)) {
|
|
95
|
+
return false
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return true
|
|
99
|
+
}
|
|
100
|
+
|
|
69
101
|
/**
|
|
70
102
|
* Type guard to validate Config object at runtime
|
|
71
103
|
* In production, caches results for performance unless SHAKAPACKER_STRICT_VALIDATION is set
|
|
@@ -79,7 +111,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
79
111
|
}
|
|
80
112
|
|
|
81
113
|
// Check cache with TTL
|
|
82
|
-
const cached = validatedConfigs.get(obj
|
|
114
|
+
const cached = validatedConfigs.get(obj)
|
|
83
115
|
if (cached && Date.now() - cached.timestamp < getCacheTTL()) {
|
|
84
116
|
if (debugCache) {
|
|
85
117
|
console.log(
|
|
@@ -104,7 +136,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
104
136
|
for (const field of requiredStringFields) {
|
|
105
137
|
if (typeof config[field] !== "string") {
|
|
106
138
|
// Cache negative result
|
|
107
|
-
validatedConfigs.set(obj
|
|
139
|
+
validatedConfigs.set(obj, {
|
|
108
140
|
result: false,
|
|
109
141
|
timestamp: Date.now()
|
|
110
142
|
})
|
|
@@ -112,14 +144,11 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
112
144
|
}
|
|
113
145
|
// SECURITY: Path traversal validation ALWAYS runs (not subject to shouldValidate)
|
|
114
146
|
// This ensures paths are safe regardless of environment or validation mode
|
|
115
|
-
if (
|
|
116
|
-
field.includes("path") &&
|
|
117
|
-
!isPathTraversalSafe(config[field] as string)
|
|
118
|
-
) {
|
|
147
|
+
if (field.includes("path") && !isPathTraversalSafe(config[field])) {
|
|
119
148
|
console.warn(
|
|
120
149
|
`[SHAKAPACKER SECURITY] Invalid path in ${field}: ${config[field]}`
|
|
121
150
|
)
|
|
122
|
-
validatedConfigs.set(obj
|
|
151
|
+
validatedConfigs.set(obj, {
|
|
123
152
|
result: false,
|
|
124
153
|
timestamp: Date.now()
|
|
125
154
|
})
|
|
@@ -142,7 +171,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
142
171
|
for (const field of requiredBooleanFields) {
|
|
143
172
|
if (typeof config[field] !== "boolean") {
|
|
144
173
|
// Cache negative result
|
|
145
|
-
validatedConfigs.set(obj
|
|
174
|
+
validatedConfigs.set(obj, {
|
|
146
175
|
result: false,
|
|
147
176
|
timestamp: Date.now()
|
|
148
177
|
})
|
|
@@ -153,7 +182,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
153
182
|
// Check arrays
|
|
154
183
|
if (!Array.isArray(config.additional_paths)) {
|
|
155
184
|
// Cache negative result
|
|
156
|
-
validatedConfigs.set(obj
|
|
185
|
+
validatedConfigs.set(obj, {
|
|
157
186
|
result: false,
|
|
158
187
|
timestamp: Date.now()
|
|
159
188
|
})
|
|
@@ -167,7 +196,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
167
196
|
console.warn(
|
|
168
197
|
`[SHAKAPACKER SECURITY] Invalid additional_path: ${additionalPath}`
|
|
169
198
|
)
|
|
170
|
-
validatedConfigs.set(obj
|
|
199
|
+
validatedConfigs.set(obj, {
|
|
171
200
|
result: false,
|
|
172
201
|
timestamp: Date.now()
|
|
173
202
|
})
|
|
@@ -179,7 +208,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
179
208
|
// Security checks above still run regardless of this flag
|
|
180
209
|
if (!shouldValidate()) {
|
|
181
210
|
// Cache positive result - basic structure and security validated
|
|
182
|
-
validatedConfigs.set(obj
|
|
211
|
+
validatedConfigs.set(obj, { result: true, timestamp: Date.now() })
|
|
183
212
|
return true
|
|
184
213
|
}
|
|
185
214
|
|
|
@@ -189,7 +218,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
189
218
|
!isValidDevServerConfig(config.dev_server)
|
|
190
219
|
) {
|
|
191
220
|
// Cache negative result
|
|
192
|
-
validatedConfigs.set(obj
|
|
221
|
+
validatedConfigs.set(obj, {
|
|
193
222
|
result: false,
|
|
194
223
|
timestamp: Date.now()
|
|
195
224
|
})
|
|
@@ -203,7 +232,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
203
232
|
typeof integrity.cross_origin !== "string"
|
|
204
233
|
) {
|
|
205
234
|
// Cache negative result
|
|
206
|
-
validatedConfigs.set(obj
|
|
235
|
+
validatedConfigs.set(obj, {
|
|
207
236
|
result: false,
|
|
208
237
|
timestamp: Date.now()
|
|
209
238
|
})
|
|
@@ -212,39 +241,7 @@ export function isValidConfig(obj: unknown): obj is Config {
|
|
|
212
241
|
}
|
|
213
242
|
|
|
214
243
|
// Cache positive result
|
|
215
|
-
validatedConfigs.set(obj
|
|
216
|
-
|
|
217
|
-
return true
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Type guard to validate DevServerConfig object at runtime
|
|
222
|
-
* In production, performs minimal validation for performance
|
|
223
|
-
*/
|
|
224
|
-
export function isValidDevServerConfig(obj: unknown): obj is DevServerConfig {
|
|
225
|
-
if (typeof obj !== "object" || obj === null) {
|
|
226
|
-
return false
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// In production, skip deep validation unless explicitly enabled
|
|
230
|
-
if (!shouldValidate()) {
|
|
231
|
-
return true
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
const config = obj as Record<string, unknown>
|
|
235
|
-
|
|
236
|
-
// All fields are optional, just check types if present
|
|
237
|
-
if (
|
|
238
|
-
config.hmr !== undefined &&
|
|
239
|
-
typeof config.hmr !== "boolean" &&
|
|
240
|
-
config.hmr !== "only"
|
|
241
|
-
) {
|
|
242
|
-
return false
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (config.port !== undefined && !validatePort(config.port)) {
|
|
246
|
-
return false
|
|
247
|
-
}
|
|
244
|
+
validatedConfigs.set(obj, { result: true, timestamp: Date.now() })
|
|
248
245
|
|
|
249
246
|
return true
|
|
250
247
|
}
|
data/package/webpack-types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @ts-
|
|
1
|
+
// @ts-expect-error: webpack is an optional peer dependency (using type-only import)
|
|
2
2
|
import type { Configuration, RuleSetRule, RuleSetUseItem } from "webpack"
|
|
3
3
|
|
|
4
4
|
export interface ShakapackerWebpackConfig extends Configuration {
|
|
@@ -13,7 +13,7 @@ export interface ShakapackerRule extends RuleSetRule {
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export interface ShakapackerLoaderOptions {
|
|
16
|
-
[key: string]:
|
|
16
|
+
[key: string]: unknown
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export interface ShakapackerLoader {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { DevServerConfig } from "./types"
|
|
2
|
+
|
|
2
3
|
const snakeToCamelCase = require("./utils/snakeToCamelCase")
|
|
3
4
|
|
|
4
5
|
const shakapackerDevServerYamlConfig =
|
|
@@ -24,11 +25,11 @@ interface WebpackDevServerConfig {
|
|
|
24
25
|
[key: string]: unknown
|
|
25
26
|
}
|
|
26
27
|
client?: Record<string, unknown>
|
|
27
|
-
allowedHosts?:
|
|
28
|
+
allowedHosts?: string | string[]
|
|
28
29
|
bonjour?: boolean | Record<string, unknown>
|
|
29
30
|
compress?: boolean
|
|
30
31
|
headers?: Record<string, unknown> | (() => Record<string, unknown>)
|
|
31
|
-
host?:
|
|
32
|
+
host?: string
|
|
32
33
|
http2?: boolean
|
|
33
34
|
https?: boolean | Record<string, unknown>
|
|
34
35
|
ipc?: boolean | string
|
|
@@ -41,12 +42,12 @@ interface WebpackDevServerConfig {
|
|
|
41
42
|
| string[]
|
|
42
43
|
| Record<string, unknown>
|
|
43
44
|
| Record<string, unknown>[]
|
|
44
|
-
port?:
|
|
45
|
+
port?: string | number
|
|
45
46
|
proxy?: unknown
|
|
46
47
|
server?: string | boolean | Record<string, unknown>
|
|
47
48
|
setupExitSignals?: boolean
|
|
48
49
|
setupMiddlewares?: (middlewares: unknown[], devServer: unknown) => unknown[]
|
|
49
|
-
watchFiles?:
|
|
50
|
+
watchFiles?: unknown
|
|
50
51
|
webSocketServer?: string | boolean | Record<string, unknown>
|
|
51
52
|
[key: string]: unknown
|
|
52
53
|
}
|
data/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shakapacker",
|
|
3
|
-
"version": "9.3.
|
|
3
|
+
"version": "9.3.1",
|
|
4
4
|
"description": "Use webpack to manage app-like JavaScript modules in Rails",
|
|
5
5
|
"homepage": "https://github.com/shakacode/shakapacker",
|
|
6
6
|
"bugs": {
|
|
@@ -74,7 +74,6 @@
|
|
|
74
74
|
"eslint-plugin-import": "^2.32.0",
|
|
75
75
|
"eslint-plugin-jest": "^29.0.1",
|
|
76
76
|
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
77
|
-
"eslint-plugin-prettier": "^5.5.4",
|
|
78
77
|
"eslint-plugin-react": "^7.37.5",
|
|
79
78
|
"eslint-plugin-react-hooks": "^7.0.0",
|
|
80
79
|
"husky": "^9.1.7",
|
|
@@ -109,7 +108,7 @@
|
|
|
109
108
|
"babel-loader": "^8.2.4 || ^9.0.0 || ^10.0.0",
|
|
110
109
|
"compression-webpack-plugin": "^9.0.0 || ^10.0.0 || ^11.0.0",
|
|
111
110
|
"css-loader": "^6.8.1 || ^7.0.0",
|
|
112
|
-
"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",
|
|
111
|
+
"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 || ^0.25.0",
|
|
113
112
|
"esbuild-loader": "^2.0.0 || ^3.0.0 || ^4.0.0",
|
|
114
113
|
"mini-css-extract-plugin": "^2.0.0",
|
|
115
114
|
"rspack-manifest-plugin": "^5.0.0",
|