shakapacker 10.3.0 → 10.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/CHANGELOG.md +16 -1
- data/lib/shakapacker/dev_server.rb +7 -2
- data/lib/shakapacker/dev_server_proxy.rb +4 -0
- data/lib/shakapacker/doctor.rb +137 -5
- data/lib/shakapacker/version.rb +1 -1
- data/package.json +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 66455bdf084a5e63422cf5741b2ce549b2dc77dcd36553e8e5fa7dcc6ce34286
|
|
4
|
+
data.tar.gz: a7030178f8ec26e3c1243fbdeb806c2746d6b14484bc99142a35f3fa3f57e9dd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: ec0476cbbaaa7044f9f06a3fe207caad61350c309164deffa47d5990e583b025c03e235b4e0e110adac394461fce264b887a71de6159a43ce5664e7a8a133992
|
|
7
|
+
data.tar.gz: 3d625e63b6f838c9febaaad2dda13d43cd7486748d7e39d6ff09e5675d06ab8b85414b9d323c41a3b09fca5adb19ec193b6d90d5651dce92f8573cd18e23937f
|
data/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,20 @@
|
|
|
10
10
|
|
|
11
11
|
## [Unreleased]
|
|
12
12
|
|
|
13
|
+
## [v10.3.1] - August 3, 2026
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
|
|
17
|
+
- **Fixed 502 responses for proxied dev server assets under `rack-proxy` v1.** [PR #1222](https://github.com/shakacode/shakapacker/pull/1222) by [jcbpl](https://github.com/jcbpl). Fixes [#1220](https://github.com/shakacode/shakapacker/issues/1220).
|
|
18
|
+
- **Fixed dev-server liveness checks treating refused macOS 27 connections as running.** The Ruby probe now verifies the connected socket's `SO_ERROR` result before proxying asset requests, avoiding false-positive dev-server detection and resulting 502 responses. [PR #1225](https://github.com/shakacode/shakapacker/pull/1225) by [justin808](https://github.com/justin808). Fixes [#1224](https://github.com/shakacode/shakapacker/issues/1224).
|
|
19
|
+
- **Fixed webpack Babel, SWC, and esbuild rules skipping explicitly included `.cjs` files.** [PR #1219](https://github.com/shakacode/shakapacker/pull/1219) by [oiahoon](https://github.com/oiahoon). Fixes [#1218](https://github.com/shakacode/shakapacker/issues/1218).
|
|
20
|
+
- **Added a `shakapacker:doctor` warning for Rspack React Refresh v2 configs that still use the v1 default-export constructor pattern.** [PR #1207](https://github.com/shakacode/shakapacker/pull/1207) by [justin808](https://github.com/justin808). Existing configs with `const ReactRefreshPlugin = require("@rspack/plugin-react-refresh")` followed by `new ReactRefreshPlugin()` can fail after upgrading to `@rspack/plugin-react-refresh` v2 with `ReactRefreshPlugin is not a constructor`; Doctor now points to the affected JS/TS config file and suggests the named-export/default/module compatibility form. Fixes [#1204](https://github.com/shakacode/shakapacker/issues/1204).
|
|
21
|
+
- **Fixed the missing-`@babel/core` failure to report an actionable install message.** [PR #1212](https://github.com/shakacode/shakapacker/pull/1212) by [justin808](https://github.com/justin808). Babel-transpiled builds whose app lacks `@babel/core` previously surfaced a raw module-resolution error from the Babel 8 compatibility check; the rule now explains which package to install and how to switch `javascript_transpiler` instead. Refs [#1163](https://github.com/shakacode/shakapacker/issues/1163).
|
|
22
|
+
|
|
23
|
+
### Documentation
|
|
24
|
+
|
|
25
|
+
- **Documented the required `css-loader@^7.1.4` in the v10 Rspack upgrade instructions.** [PR #1211](https://github.com/shakacode/shakapacker/pull/1211) by [justin808](https://github.com/justin808). The v10 upgrade guide's copy-paste Rspack v2 commands omitted `css-loader`, so apps following them could upgrade into an unsatisfied peer dependency.
|
|
26
|
+
|
|
13
27
|
## [v10.3.0] - July 5, 2026
|
|
14
28
|
|
|
15
29
|
### Added
|
|
@@ -986,7 +1000,8 @@ Note: [Rubygem is 6.3.0.pre.rc.1](https://rubygems.org/gems/shakapacker/versions
|
|
|
986
1000
|
|
|
987
1001
|
See [CHANGELOG.md in rails/webpacker (up to v5.4.3)](https://github.com/rails/webpacker/blob/master/CHANGELOG.md)
|
|
988
1002
|
|
|
989
|
-
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.3.
|
|
1003
|
+
[Unreleased]: https://github.com/shakacode/shakapacker/compare/v10.3.1...main
|
|
1004
|
+
[v10.3.1]: https://github.com/shakacode/shakapacker/compare/v10.3.0...v10.3.1
|
|
990
1005
|
[v10.3.0]: https://github.com/shakacode/shakapacker/compare/v10.2.0...v10.3.0
|
|
991
1006
|
[v10.2.0]: https://github.com/shakacode/shakapacker/compare/v10.1.0...v10.2.0
|
|
992
1007
|
[v10.1.0]: https://github.com/shakacode/shakapacker/compare/v10.0.0...v10.1.0
|
|
@@ -47,8 +47,13 @@ class Shakapacker::DevServer
|
|
|
47
47
|
# @return [Boolean] true if the dev server is running
|
|
48
48
|
def running?
|
|
49
49
|
if config.dev_server.present?
|
|
50
|
-
Socket.tcp(host, port, connect_timeout: connect_timeout)
|
|
51
|
-
|
|
50
|
+
socket = Socket.tcp(host, port, connect_timeout: connect_timeout)
|
|
51
|
+
|
|
52
|
+
begin
|
|
53
|
+
socket.getsockopt(Socket::SOL_SOCKET, Socket::SO_ERROR).int.zero?
|
|
54
|
+
ensure
|
|
55
|
+
socket.close
|
|
56
|
+
end
|
|
52
57
|
else
|
|
53
58
|
false
|
|
54
59
|
end
|
|
@@ -11,6 +11,10 @@ class Shakapacker::DevServerProxy < Rack::Proxy
|
|
|
11
11
|
|
|
12
12
|
def perform_request(env)
|
|
13
13
|
if env["PATH_INFO"].start_with?("/#{public_output_uri_path}") && dev_server.running?
|
|
14
|
+
# rack-proxy v1 refuses to derive the backend from the Host header.
|
|
15
|
+
env["rack.backend"] = URI::Generic.build(
|
|
16
|
+
scheme: dev_server.protocol, host: dev_server.host, port: dev_server.port
|
|
17
|
+
)
|
|
14
18
|
env["HTTP_HOST"] = env["HTTP_X_FORWARDED_HOST"] = dev_server.host
|
|
15
19
|
env["HTTP_X_FORWARDED_SERVER"] = dev_server.host_with_port
|
|
16
20
|
env["HTTP_PORT"] = env["HTTP_X_FORWARDED_PORT"] = dev_server.port.to_s
|
data/lib/shakapacker/doctor.rb
CHANGED
|
@@ -59,6 +59,9 @@ module Shakapacker
|
|
|
59
59
|
"@rspack/plugin-react-refresh" => "^2.0.0"
|
|
60
60
|
}.freeze
|
|
61
61
|
|
|
62
|
+
RSPACK_REACT_REFRESH_PACKAGE = "@rspack/plugin-react-refresh".freeze
|
|
63
|
+
VERSION_UPPER_BOUND_OPERATORS = %w[< <=].freeze
|
|
64
|
+
|
|
62
65
|
CUSTOM_HYBRID_LOADER_DEPS = %w[
|
|
63
66
|
babel-loader
|
|
64
67
|
esbuild-loader
|
|
@@ -170,6 +173,7 @@ module Shakapacker
|
|
|
170
173
|
check_css_modules_configuration
|
|
171
174
|
check_bundler_dependencies if config_exists?
|
|
172
175
|
check_rspack_cache_configuration if config_exists?
|
|
176
|
+
check_rspack_react_refresh_plugin_constructor if config_exists?
|
|
173
177
|
check_file_type_dependencies if config_exists?
|
|
174
178
|
check_sri_dependencies if config_exists?
|
|
175
179
|
check_peer_dependencies
|
|
@@ -878,14 +882,89 @@ module Shakapacker
|
|
|
878
882
|
"See https://rspack.rs/config/cache for options.")
|
|
879
883
|
end
|
|
880
884
|
|
|
885
|
+
def check_rspack_react_refresh_plugin_constructor
|
|
886
|
+
return unless rspack_react_refresh_check_applicable?
|
|
887
|
+
return unless rspack_react_refresh_plugin_v2_or_newer?
|
|
888
|
+
|
|
889
|
+
rspack_react_refresh_config_paths.each do |path|
|
|
890
|
+
content = File.read(path)
|
|
891
|
+
next unless legacy_rspack_react_refresh_constructor?(content)
|
|
892
|
+
|
|
893
|
+
relative = config_path_for_warning(path)
|
|
894
|
+
add_action_required("Rspack React Refresh config #{relative} uses the " \
|
|
895
|
+
"#{RSPACK_REACT_REFRESH_PACKAGE} v1 default-export constructor pattern. " \
|
|
896
|
+
"With #{RSPACK_REACT_REFRESH_PACKAGE} v2, rspack may fail with " \
|
|
897
|
+
"'ReactRefreshPlugin is not a constructor'.")
|
|
898
|
+
add_fix_hint("Use a compat constructor: const ReactRefresh = require(\"#{RSPACK_REACT_REFRESH_PACKAGE}\"); " \
|
|
899
|
+
"const ReactRefreshRspackPlugin = ReactRefresh.ReactRefreshRspackPlugin || " \
|
|
900
|
+
"ReactRefresh.default || ReactRefresh; then call new ReactRefreshRspackPlugin().")
|
|
901
|
+
rescue SystemCallError => e
|
|
902
|
+
add_info_warning("Unable to validate Rspack React Refresh config #{config_path_for_warning(path)}: #{e.message}")
|
|
903
|
+
end
|
|
904
|
+
end
|
|
905
|
+
|
|
906
|
+
def rspack_react_refresh_check_applicable?
|
|
907
|
+
assets_bundler == "rspack" || unconfigured_hybrid_loader_graph?
|
|
908
|
+
end
|
|
909
|
+
|
|
910
|
+
def rspack_react_refresh_plugin_v2_or_newer?
|
|
911
|
+
version = installed_package_version(RSPACK_REACT_REFRESH_PACKAGE)
|
|
912
|
+
return version >= Gem::Version.new("2.0.0") if version
|
|
913
|
+
|
|
914
|
+
package_specifier_allows_version_or_newer?(
|
|
915
|
+
package_json_dependency_version(RSPACK_REACT_REFRESH_PACKAGE),
|
|
916
|
+
Gem::Version.new("2.0.0")
|
|
917
|
+
)
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
def rspack_react_refresh_config_paths
|
|
921
|
+
config_dir = rspack_react_refresh_config_dir
|
|
922
|
+
config_dir_path = Pathname.new(File.join(root_path.to_s, config_dir))
|
|
923
|
+
return [] unless config_dir_path.directory?
|
|
924
|
+
|
|
925
|
+
path = active_bundler_config_path_in(config_dir)
|
|
926
|
+
path ? [path] : []
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
def rspack_react_refresh_config_dir
|
|
930
|
+
config_dir = config.assets_bundler_config_path.to_s
|
|
931
|
+
|
|
932
|
+
if assets_bundler == "rspack" || same_directory_hybrid_config_present?(config_dir)
|
|
933
|
+
config_dir
|
|
934
|
+
else
|
|
935
|
+
"config/rspack"
|
|
936
|
+
end
|
|
937
|
+
end
|
|
938
|
+
|
|
939
|
+
def legacy_rspack_react_refresh_constructor?(content)
|
|
940
|
+
stripped = strip_rspack_config_comments_and_literals(content, preserve_literals: [RSPACK_REACT_REFRESH_PACKAGE])
|
|
941
|
+
constructor_names = []
|
|
942
|
+
|
|
943
|
+
constructor_names.concat(stripped.scan(
|
|
944
|
+
/\b(?:const|let|var)\s+([A-Za-z_$][\w$]*)\s*=\s*require\(\s*["']#{Regexp.escape(RSPACK_REACT_REFRESH_PACKAGE)}["']\s*\)(?=\s*(?:[;,\)]|$))/
|
|
945
|
+
).flatten)
|
|
946
|
+
constructor_names.concat(stripped.scan(
|
|
947
|
+
/\bimport\s+([A-Za-z_$][\w$]*)\s*(?:,\s*\{[^}]*\}\s*)?\s+from\s*["']#{Regexp.escape(RSPACK_REACT_REFRESH_PACKAGE)}["']/
|
|
948
|
+
).flatten)
|
|
949
|
+
constructor_names.concat(stripped.scan(
|
|
950
|
+
/\bimport\s+\*\s+as\s+([A-Za-z_$][\w$]*)\s+from\s*["']#{Regexp.escape(RSPACK_REACT_REFRESH_PACKAGE)}["']/
|
|
951
|
+
).flatten)
|
|
952
|
+
|
|
953
|
+
constructor_names.uniq.any? do |constructor_name|
|
|
954
|
+
stripped.match?(/\bnew\s+#{Regexp.escape(constructor_name)}\s*\(/)
|
|
955
|
+
end
|
|
956
|
+
end
|
|
957
|
+
|
|
881
958
|
# Returns the single active config path the runner would load, or nil. Mirrors the
|
|
882
959
|
# resolution order in Shakapacker::Runner#find_rspack_config_with_fallback so the
|
|
883
960
|
# doctor inspects the same file the build will actually use (and so unused sibling
|
|
884
961
|
# configs in the same directory don't trigger spurious warnings).
|
|
885
962
|
# NOTE: keep this candidate list in sync with Runner#find_rspack_config_with_fallback.
|
|
886
963
|
def active_assets_bundler_config_path
|
|
887
|
-
|
|
964
|
+
active_bundler_config_path_in(config.assets_bundler_config_path.to_s)
|
|
965
|
+
end
|
|
888
966
|
|
|
967
|
+
def active_bundler_config_path_in(config_dir)
|
|
889
968
|
candidates = %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, config_dir, "rspack.config.#{ext}")) }
|
|
890
969
|
candidates += %w[ts js].map { |ext| Pathname.new(File.join(root_path.to_s, config_dir, "webpack.config.#{ext}")) }
|
|
891
970
|
if default_rspack_config_dir?(config_dir)
|
|
@@ -944,7 +1023,7 @@ module Shakapacker
|
|
|
944
1023
|
stripped.gsub(%r{/(?:\\.|\[[^\]\n]*\]|[^/\n\\\[])+?/[gimsuy]*}, "")
|
|
945
1024
|
end
|
|
946
1025
|
|
|
947
|
-
def strip_rspack_config_comments_and_literals(content)
|
|
1026
|
+
def strip_rspack_config_comments_and_literals(content, preserve_literals: [])
|
|
948
1027
|
stripped = +""
|
|
949
1028
|
index = 0
|
|
950
1029
|
|
|
@@ -987,8 +1066,12 @@ module Shakapacker
|
|
|
987
1066
|
end
|
|
988
1067
|
|
|
989
1068
|
literal = content[index...literal_end]
|
|
990
|
-
|
|
991
|
-
|
|
1069
|
+
if preserved_js_string_literal?(literal, char, preserve_literals)
|
|
1070
|
+
stripped << literal
|
|
1071
|
+
else
|
|
1072
|
+
stripped << '""'
|
|
1073
|
+
stripped << literal.gsub(/[^\n]/, "")
|
|
1074
|
+
end
|
|
992
1075
|
index = literal_end
|
|
993
1076
|
elsif char == "`"
|
|
994
1077
|
literal_end = index + 1
|
|
@@ -1029,6 +1112,12 @@ module Shakapacker
|
|
|
1029
1112
|
stripped
|
|
1030
1113
|
end
|
|
1031
1114
|
|
|
1115
|
+
def preserved_js_string_literal?(literal, quote, preserve_literals)
|
|
1116
|
+
return false unless literal.end_with?(quote)
|
|
1117
|
+
|
|
1118
|
+
preserve_literals.include?(literal[1...-1])
|
|
1119
|
+
end
|
|
1120
|
+
|
|
1032
1121
|
def direct_export_cache_disabled?(stripped)
|
|
1033
1122
|
# Match `cache: false` only near an exported config object at brace depth
|
|
1034
1123
|
# 1. This avoids warning on local base config objects while still
|
|
@@ -1183,8 +1272,9 @@ module Shakapacker
|
|
|
1183
1272
|
return versions.min
|
|
1184
1273
|
end
|
|
1185
1274
|
|
|
1275
|
+
return package_version_from_range_specifier(cleaned) if cleaned.match?(/[<>=]/)
|
|
1186
1276
|
return nil unless cleaned.match?(/\A[\^~]?\d/)
|
|
1187
|
-
return nil if cleaned.match?(/(\s
|
|
1277
|
+
return nil if cleaned.match?(/(\s|\|\||:|\A(?:git|file|link|workspace|npm):)/)
|
|
1188
1278
|
|
|
1189
1279
|
match = cleaned.sub(/\A[\^~]/, "").match(/\A(\d+(?:\.\d+){0,2})(?:-[0-9A-Za-z.-]+)?\z/)
|
|
1190
1280
|
match && Gem::Version.new(match[1])
|
|
@@ -1192,6 +1282,48 @@ module Shakapacker
|
|
|
1192
1282
|
nil
|
|
1193
1283
|
end
|
|
1194
1284
|
|
|
1285
|
+
def package_version_from_range_specifier(specifier)
|
|
1286
|
+
lower_bounds = specifier.scan(/(?:\A|\s)(?:>=|>)\s*(\d+(?:\.\d+){0,2})(?:-[0-9A-Za-z.-]+)?/)
|
|
1287
|
+
versions = lower_bounds.flatten.map { |version| Gem::Version.new(version) }
|
|
1288
|
+
|
|
1289
|
+
versions.max
|
|
1290
|
+
rescue ArgumentError
|
|
1291
|
+
nil
|
|
1292
|
+
end
|
|
1293
|
+
|
|
1294
|
+
def package_specifier_allows_version_or_newer?(specifier, minimum)
|
|
1295
|
+
return false unless specifier
|
|
1296
|
+
|
|
1297
|
+
cleaned = specifier.strip
|
|
1298
|
+
if cleaned.include?("||")
|
|
1299
|
+
return cleaned.split("||").any? { |part| package_specifier_allows_version_or_newer?(part, minimum) }
|
|
1300
|
+
end
|
|
1301
|
+
return false if cleaned.match?(/(:|\A(?:git|file|link|workspace|npm):)/)
|
|
1302
|
+
|
|
1303
|
+
if cleaned.match?(/[<>=]/)
|
|
1304
|
+
return package_range_specifier_allows_version_or_newer?(cleaned, minimum)
|
|
1305
|
+
end
|
|
1306
|
+
|
|
1307
|
+
version = package_version_from_specifier(cleaned)
|
|
1308
|
+
version && version >= minimum
|
|
1309
|
+
end
|
|
1310
|
+
|
|
1311
|
+
def package_range_specifier_allows_version_or_newer?(specifier, minimum)
|
|
1312
|
+
comparators = specifier.scan(/(?:\A|\s)(<=|<|>=|>|=)\s*(\d+(?:\.\d+){0,2})(?:-[0-9A-Za-z.-]+)?/)
|
|
1313
|
+
return false if comparators.empty?
|
|
1314
|
+
|
|
1315
|
+
equalities = comparators.select { |operator, _version| operator == "=" }
|
|
1316
|
+
return equalities.any? { |_operator, version| Gem::Version.new(version) >= minimum } if equalities.any?
|
|
1317
|
+
|
|
1318
|
+
upper_bounds = comparators.select { |operator, _version| VERSION_UPPER_BOUND_OPERATORS.include?(operator) }
|
|
1319
|
+
upper_bounds.all? do |operator, version|
|
|
1320
|
+
parsed = Gem::Version.new(version)
|
|
1321
|
+
operator == "<" ? parsed > minimum : parsed >= minimum
|
|
1322
|
+
end
|
|
1323
|
+
rescue ArgumentError
|
|
1324
|
+
false
|
|
1325
|
+
end
|
|
1326
|
+
|
|
1195
1327
|
def declared_package_dependencies
|
|
1196
1328
|
@declared_package_dependencies ||= begin
|
|
1197
1329
|
package_json_paths.reverse_each.each_with_object({}) do |path, dependencies|
|
data/lib/shakapacker/version.rb
CHANGED
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shakapacker
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 10.3.
|
|
4
|
+
version: 10.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- David Heinemeier Hansson
|
|
@@ -225,7 +225,7 @@ homepage: https://github.com/shakacode/shakapacker
|
|
|
225
225
|
licenses:
|
|
226
226
|
- MIT
|
|
227
227
|
metadata:
|
|
228
|
-
source_code_uri: https://github.com/shakacode/shakapacker/tree/v10.3.
|
|
228
|
+
source_code_uri: https://github.com/shakacode/shakapacker/tree/v10.3.1
|
|
229
229
|
rdoc_options: []
|
|
230
230
|
require_paths:
|
|
231
231
|
- lib
|