react_on_rails 14.2.1 → 16.1.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/AI_AGENT_INSTRUCTIONS.md +63 -0
- data/CHANGELOG.md +564 -85
- data/CLAUDE.md +135 -0
- data/CODING_AGENTS.md +313 -0
- data/CONTRIBUTING.md +448 -37
- data/Gemfile.development_dependencies +6 -1
- data/Gemfile.lock +13 -4
- data/KUDOS.md +22 -1
- data/LICENSE.md +30 -4
- data/LICENSES/README.md +14 -0
- data/NEWS.md +48 -48
- data/PROJECTS.md +45 -40
- data/REACT-ON-RAILS-PRO-LICENSE.md +129 -0
- data/README.md +113 -42
- data/SUMMARY.md +62 -52
- data/TODO.md +135 -0
- data/bin/lefthook/check-trailing-newlines +38 -0
- data/bin/lefthook/get-changed-files +26 -0
- data/bin/lefthook/prettier-format +26 -0
- data/bin/lefthook/ruby-autofix +26 -0
- data/bin/lefthook/ruby-lint +27 -0
- data/eslint.config.ts +232 -0
- data/knip.ts +40 -6
- data/lib/generators/USAGE +4 -5
- data/lib/generators/react_on_rails/USAGE +65 -0
- data/lib/generators/react_on_rails/base_generator.rb +276 -62
- data/lib/generators/react_on_rails/dev_tests_generator.rb +1 -0
- data/lib/generators/react_on_rails/generator_helper.rb +35 -1
- data/lib/generators/react_on_rails/generator_messages.rb +138 -17
- data/lib/generators/react_on_rails/install_generator.rb +474 -26
- data/lib/generators/react_on_rails/react_no_redux_generator.rb +19 -6
- data/lib/generators/react_on_rails/react_with_redux_generator.rb +110 -18
- data/lib/generators/react_on_rails/templates/.eslintrc +1 -1
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev +5 -0
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-prod-assets +8 -0
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static-assets +2 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +0 -5
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +2 -2
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/bundles/HelloWorld/components/HelloWorldServer.js +1 -1
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/server-bundle.js +1 -8
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx +21 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.tsx +25 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.module.css +4 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.jsx +5 -0
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.server.tsx +5 -0
- data/lib/generators/react_on_rails/templates/base/base/app/views/hello_world/index.html.erb.tt +1 -1
- data/lib/generators/react_on_rails/templates/base/base/app/views/layouts/hello_world.html.erb +4 -2
- data/lib/generators/react_on_rails/templates/base/base/babel.config.js.tt +5 -2
- data/lib/generators/react_on_rails/templates/base/base/bin/dev +34 -0
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +14 -5
- data/lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml +76 -7
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/commonWebpackConfig.js.tt +1 -1
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +6 -10
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/production.js.tt +2 -2
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +3 -2
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/test.js.tt +2 -2
- data/lib/generators/react_on_rails/templates/dev_tests/spec/system/hello_world_spec.rb +0 -2
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/actions/helloWorldActionCreators.ts +18 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.jsx +0 -6
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.module.css +4 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/components/HelloWorld.tsx +24 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/constants/helloWorldConstants.ts +6 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/containers/HelloWorldContainer.ts +20 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/reducers/helloWorldReducer.js +1 -1
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/reducers/helloWorldReducer.ts +22 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.client.tsx +23 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.server.jsx +5 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/HelloWorldApp.server.tsx +5 -0
- data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/store/helloWorldStore.ts +18 -0
- data/lib/react_on_rails/configuration.rb +141 -57
- data/lib/react_on_rails/controller.rb +6 -2
- data/lib/react_on_rails/dev/file_manager.rb +78 -0
- data/lib/react_on_rails/dev/pack_generator.rb +27 -0
- data/lib/react_on_rails/dev/process_manager.rb +61 -0
- data/lib/react_on_rails/dev/server_manager.rb +487 -0
- data/lib/react_on_rails/dev.rb +20 -0
- data/lib/react_on_rails/doctor.rb +1149 -0
- data/lib/react_on_rails/engine.rb +6 -0
- data/lib/react_on_rails/git_utils.rb +12 -2
- data/lib/react_on_rails/helper.rb +176 -74
- data/lib/react_on_rails/json_parse_error.rb +6 -1
- data/lib/react_on_rails/packer_utils.rb +61 -71
- data/lib/react_on_rails/packs_generator.rb +221 -19
- data/lib/react_on_rails/prerender_error.rb +4 -0
- data/lib/react_on_rails/pro/NOTICE +21 -0
- data/lib/react_on_rails/pro/helper.rb +122 -0
- data/lib/react_on_rails/pro/utils.rb +53 -0
- data/lib/react_on_rails/react_component/render_options.rb +38 -6
- data/lib/react_on_rails/server_rendering_js_code.rb +0 -1
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +12 -5
- data/lib/react_on_rails/system_checker.rb +659 -0
- data/lib/react_on_rails/test_helper/webpack_assets_compiler.rb +1 -1
- data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +6 -4
- data/lib/react_on_rails/test_helper.rb +2 -3
- data/lib/react_on_rails/utils.rb +139 -43
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/version_checker.rb +14 -20
- data/lib/react_on_rails/version_syntax_converter.rb +1 -1
- data/lib/react_on_rails.rb +1 -0
- data/lib/tasks/assets.rake +1 -1
- data/lib/tasks/doctor.rake +48 -0
- data/lib/tasks/generate_packs.rake +158 -1
- data/react_on_rails.gemspec +1 -0
- data/tsconfig.eslint.json +6 -0
- data/tsconfig.json +5 -3
- metadata +63 -14
- data/REACT-ON-RAILS-PRO-LICENSE +0 -95
- data/lib/generators/react_on_rails/adapt_for_older_shakapacker_generator.rb +0 -41
- data/lib/generators/react_on_rails/bin/dev +0 -30
- data/lib/generators/react_on_rails/bin/dev-static +0 -30
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev-static.tt +0 -9
- data/lib/generators/react_on_rails/templates/base/base/Procfile.dev.tt +0 -5
- data/lib/generators/react_on_rails/templates/base/base/app/javascript/packs/registration.js.tt +0 -8
- /data/lib/generators/react_on_rails/templates/base/base/config/webpack/{webpackConfig.js.tt → generateWebpackConfigs.js.tt} +0 -0
- /data/lib/generators/react_on_rails/templates/redux/base/app/javascript/bundles/HelloWorld/startup/{HelloWorldApp.jsx → HelloWorldApp.client.jsx} +0 -0
@@ -86,10 +86,9 @@ module ReactOnRails
|
|
86
86
|
puts
|
87
87
|
@printed_once = true
|
88
88
|
|
89
|
-
if ReactOnRails::
|
90
|
-
ReactOnRails::Utils.using_packer_source_path_is_not_defined_and_custom_node_modules?
|
89
|
+
if ReactOnRails::Utils.using_packer_source_path_is_not_defined_and_custom_node_modules?
|
91
90
|
msg = <<-MSG.strip_heredoc
|
92
|
-
WARNING: Define config
|
91
|
+
WARNING: Define config/shakapacker.yml to include sourcePath to configure
|
93
92
|
the location of your JavaScript source for React on Rails.
|
94
93
|
Default location of #{source_path} is used.
|
95
94
|
MSG
|
data/lib/react_on_rails/utils.rb
CHANGED
@@ -6,6 +6,7 @@ require "rainbow"
|
|
6
6
|
require "active_support"
|
7
7
|
require "active_support/core_ext/string"
|
8
8
|
|
9
|
+
# rubocop:disable Metrics/ModuleLength
|
9
10
|
module ReactOnRails
|
10
11
|
module Utils
|
11
12
|
TRUNCATION_FILLER = "\n... TRUNCATED #{
|
@@ -57,6 +58,8 @@ module ReactOnRails
|
|
57
58
|
MSG
|
58
59
|
|
59
60
|
puts wrap_message(msg)
|
61
|
+
puts ""
|
62
|
+
puts default_troubleshooting_section
|
60
63
|
|
61
64
|
# Rspec catches exit without! in the exit callbacks
|
62
65
|
exit!(1)
|
@@ -68,44 +71,107 @@ module ReactOnRails
|
|
68
71
|
server_bundle_js_file_path =~ %r{https?://}
|
69
72
|
end
|
70
73
|
|
74
|
+
def self.bundle_js_file_path(bundle_name)
|
75
|
+
# Priority order depends on bundle type:
|
76
|
+
# SERVER BUNDLES (normal case): Try private non-public locations first, then manifest, then legacy
|
77
|
+
# CLIENT BUNDLES (normal case): Try manifest first, then fallback locations
|
78
|
+
if bundle_name == "manifest.json"
|
79
|
+
# Default to the non-hashed name in the specified output directory, which, for legacy
|
80
|
+
# React on Rails, this is the output directory picked up by the asset pipeline.
|
81
|
+
# For Shakapacker, this is the public output path defined in the (shaka/web)packer.yml file.
|
82
|
+
File.join(public_bundles_full_path, bundle_name)
|
83
|
+
else
|
84
|
+
bundle_js_file_path_with_packer(bundle_name)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
private_class_method def self.bundle_js_file_path_with_packer(bundle_name)
|
89
|
+
is_server_bundle = server_bundle?(bundle_name)
|
90
|
+
config = ReactOnRails.configuration
|
91
|
+
root_path = Rails.root || "."
|
92
|
+
|
93
|
+
# If server bundle and server_bundle_output_path is configured, return that path directly
|
94
|
+
if is_server_bundle && config.server_bundle_output_path.present?
|
95
|
+
private_server_bundle_path = File.expand_path(File.join(root_path, config.server_bundle_output_path,
|
96
|
+
bundle_name))
|
97
|
+
|
98
|
+
# Don't fall back to public directory if enforce_private_server_bundles is enabled
|
99
|
+
if config.enforce_private_server_bundles || File.exist?(private_server_bundle_path)
|
100
|
+
return private_server_bundle_path
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Try manifest lookup for all bundles
|
105
|
+
begin
|
106
|
+
ReactOnRails::PackerUtils.bundle_js_uri_from_packer(bundle_name)
|
107
|
+
rescue Shakapacker::Manifest::MissingEntryError
|
108
|
+
handle_missing_manifest_entry(bundle_name, is_server_bundle)
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
private_class_method def self.server_bundle?(bundle_name)
|
113
|
+
config = ReactOnRails.configuration
|
114
|
+
bundle_name == config.server_bundle_js_file ||
|
115
|
+
bundle_name == config.rsc_bundle_js_file ||
|
116
|
+
bundle_name == config.react_server_client_manifest_file
|
117
|
+
end
|
118
|
+
|
119
|
+
private_class_method def self.handle_missing_manifest_entry(bundle_name, is_server_bundle)
|
120
|
+
config = ReactOnRails.configuration
|
121
|
+
root_path = Rails.root || "."
|
122
|
+
|
123
|
+
# For server bundles with server_bundle_output_path configured, use that
|
124
|
+
if is_server_bundle && config.server_bundle_output_path.present?
|
125
|
+
candidate_paths = [File.expand_path(File.join(root_path, config.server_bundle_output_path, bundle_name))]
|
126
|
+
unless config.enforce_private_server_bundles
|
127
|
+
candidate_paths << File.expand_path(File.join(ReactOnRails::PackerUtils.packer_public_output_path,
|
128
|
+
bundle_name))
|
129
|
+
end
|
130
|
+
|
131
|
+
candidate_paths.each do |path|
|
132
|
+
return path if File.exist?(path)
|
133
|
+
end
|
134
|
+
return candidate_paths.first
|
135
|
+
end
|
136
|
+
|
137
|
+
# For client bundles and server bundles without special config, use packer's public path
|
138
|
+
# This returns the environment-specific path configured in shakapacker.yml
|
139
|
+
File.expand_path(File.join(ReactOnRails::PackerUtils.packer_public_output_path, bundle_name))
|
140
|
+
end
|
141
|
+
|
71
142
|
def self.server_bundle_js_file_path
|
72
|
-
# Either:
|
73
|
-
# 1. Using same bundle for both server and client, so server bundle will be hashed in manifest
|
74
|
-
# 2. Using a different bundle (different Webpack config), so file is not hashed, and
|
75
|
-
# bundle_js_path will throw so the default path is used without a hash.
|
76
|
-
# 3. The third option of having the server bundle hashed and a different configuration than
|
77
|
-
# the client bundle is not supported for 2 reasons:
|
78
|
-
# a. The webpack manifest plugin would have a race condition where the same manifest.json
|
79
|
-
# is edited by both the webpack-dev-server
|
80
|
-
# b. There is no good reason to hash the server bundle name.
|
81
143
|
return @server_bundle_path if @server_bundle_path && !Rails.env.development?
|
82
144
|
|
83
145
|
bundle_name = ReactOnRails.configuration.server_bundle_js_file
|
84
|
-
@server_bundle_path =
|
85
|
-
begin
|
86
|
-
bundle_js_file_path(bundle_name)
|
87
|
-
rescue Object.const_get(
|
88
|
-
ReactOnRails::PackerUtils.packer_type.capitalize
|
89
|
-
)::Manifest::MissingEntryError
|
90
|
-
File.expand_path(
|
91
|
-
File.join(ReactOnRails::PackerUtils.packer_public_output_path,
|
92
|
-
bundle_name)
|
93
|
-
)
|
94
|
-
end
|
95
|
-
else
|
96
|
-
bundle_js_file_path(bundle_name)
|
97
|
-
end
|
146
|
+
@server_bundle_path = bundle_js_file_path(bundle_name)
|
98
147
|
end
|
99
148
|
|
100
|
-
def self.
|
101
|
-
if
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
149
|
+
def self.rsc_bundle_js_file_path
|
150
|
+
return @rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?
|
151
|
+
|
152
|
+
bundle_name = ReactOnRails.configuration.rsc_bundle_js_file
|
153
|
+
@rsc_bundle_path = bundle_js_file_path(bundle_name)
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.react_client_manifest_file_path
|
157
|
+
return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?
|
158
|
+
|
159
|
+
file_name = ReactOnRails.configuration.react_client_manifest_file
|
160
|
+
@react_client_manifest_path = ReactOnRails::PackerUtils.asset_uri_from_packer(file_name)
|
161
|
+
end
|
162
|
+
|
163
|
+
# React Server Manifest is generated by the server bundle.
|
164
|
+
# So, it will never be served from the dev server.
|
165
|
+
def self.react_server_client_manifest_file_path
|
166
|
+
return @react_server_manifest_path if @react_server_manifest_path && !Rails.env.development?
|
167
|
+
|
168
|
+
asset_name = ReactOnRails.configuration.react_server_client_manifest_file
|
169
|
+
if asset_name.nil?
|
170
|
+
raise ReactOnRails::Error,
|
171
|
+
"react_server_client_manifest_file is nil, ensure it is set in your configuration"
|
108
172
|
end
|
173
|
+
|
174
|
+
@react_server_manifest_path = bundle_js_file_path(asset_name)
|
109
175
|
end
|
110
176
|
|
111
177
|
def self.running_on_windows?
|
@@ -133,26 +199,21 @@ module ReactOnRails
|
|
133
199
|
end
|
134
200
|
|
135
201
|
def self.source_path
|
136
|
-
|
137
|
-
ReactOnRails::PackerUtils.packer_source_path
|
138
|
-
else
|
139
|
-
ReactOnRails.configuration.node_modules_location
|
140
|
-
end
|
202
|
+
ReactOnRails::PackerUtils.packer_source_path
|
141
203
|
end
|
142
204
|
|
143
205
|
def self.using_packer_source_path_is_not_defined_and_custom_node_modules?
|
144
|
-
return false unless ReactOnRails::PackerUtils.using_packer?
|
145
|
-
|
146
206
|
!ReactOnRails::PackerUtils.packer_source_path_explicit? &&
|
147
207
|
ReactOnRails.configuration.node_modules_location.present?
|
148
208
|
end
|
149
209
|
|
210
|
+
def self.public_bundles_full_path
|
211
|
+
ReactOnRails::PackerUtils.packer_public_output_path
|
212
|
+
end
|
213
|
+
|
214
|
+
# DEPRECATED: Use public_bundles_full_path for clarity about public vs private bundle paths
|
150
215
|
def self.generated_assets_full_path
|
151
|
-
|
152
|
-
ReactOnRails::PackerUtils.packer_public_output_path
|
153
|
-
else
|
154
|
-
File.expand_path(ReactOnRails.configuration.generated_assets_dir)
|
155
|
-
end
|
216
|
+
public_bundles_full_path
|
156
217
|
end
|
157
218
|
|
158
219
|
def self.gem_available?(name)
|
@@ -185,6 +246,30 @@ module ReactOnRails
|
|
185
246
|
end
|
186
247
|
end
|
187
248
|
|
249
|
+
def self.react_on_rails_pro_licence_valid?
|
250
|
+
return @react_on_rails_pro_licence_valid if defined?(@react_on_rails_pro_licence_valid)
|
251
|
+
|
252
|
+
@react_on_rails_pro_licence_valid = begin
|
253
|
+
return false unless react_on_rails_pro?
|
254
|
+
|
255
|
+
# Maintain compatibility with legacy versions of React on Rails Pro:
|
256
|
+
# Earlier releases did not require license validation, as they were distributed as private gems.
|
257
|
+
# This check ensures that the method works correctly regardless of the installed version.
|
258
|
+
return true unless ReactOnRailsPro::Utils.respond_to?(:licence_valid?)
|
259
|
+
|
260
|
+
ReactOnRailsPro::Utils.licence_valid?
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
def self.rsc_support_enabled?
|
265
|
+
return false unless react_on_rails_pro?
|
266
|
+
|
267
|
+
return @rsc_support_enabled if defined?(@rsc_support_enabled)
|
268
|
+
|
269
|
+
rorp_config = ReactOnRailsPro.configuration
|
270
|
+
@rsc_support_enabled = rorp_config.respond_to?(:enable_rsc_support) && rorp_config.enable_rsc_support
|
271
|
+
end
|
272
|
+
|
188
273
|
def self.full_text_errors_enabled?
|
189
274
|
ENV["FULL_TEXT_ERRORS"] == "true"
|
190
275
|
end
|
@@ -226,5 +311,16 @@ module ReactOnRails
|
|
226
311
|
|
227
312
|
puts "Prepended\n#{text_to_prepend}to #{file}."
|
228
313
|
end
|
314
|
+
|
315
|
+
def self.default_troubleshooting_section
|
316
|
+
<<~DEFAULT
|
317
|
+
📞 Get Help & Support:
|
318
|
+
• 🚀 Professional Support: react_on_rails@shakacode.com (fastest resolution)
|
319
|
+
• 💬 React + Rails Slack: https://invite.reactrails.com
|
320
|
+
• 🆓 GitHub Issues: https://github.com/shakacode/react_on_rails/issues
|
321
|
+
• 📖 Discussions: https://github.com/shakacode/react_on_rails/discussions
|
322
|
+
DEFAULT
|
323
|
+
end
|
229
324
|
end
|
230
325
|
end
|
326
|
+
# rubocop:enable Metrics/ModuleLength
|
@@ -6,7 +6,8 @@ module ReactOnRails
|
|
6
6
|
class VersionChecker
|
7
7
|
attr_reader :node_package_version
|
8
8
|
|
9
|
-
|
9
|
+
# Semver uses - to separate pre-release, but RubyGems use .
|
10
|
+
VERSION_PARTS_REGEX = /(\d+)\.(\d+)\.(\d+)(?:[-.]([0-9A-Za-z.-]+))?/
|
10
11
|
|
11
12
|
def self.build
|
12
13
|
new(NodePackageVersion.build)
|
@@ -23,13 +24,7 @@ module ReactOnRails
|
|
23
24
|
return if node_package_version.raw.nil? || node_package_version.local_path_or_url?
|
24
25
|
return log_node_semver_version_warning if node_package_version.semver_wildcard?
|
25
26
|
|
26
|
-
|
27
|
-
gem_major_minor_patch = gem_major_minor_patch_version
|
28
|
-
versions_match = node_major_minor_patch[0] == gem_major_minor_patch[0] &&
|
29
|
-
node_major_minor_patch[1] == gem_major_minor_patch[1] &&
|
30
|
-
node_major_minor_patch[2] == gem_major_minor_patch[2]
|
31
|
-
|
32
|
-
log_differing_versions_warning unless versions_match
|
27
|
+
log_differing_versions_warning unless node_package_version.parts == gem_version_parts
|
33
28
|
end
|
34
29
|
|
35
30
|
private
|
@@ -39,20 +34,20 @@ module ReactOnRails
|
|
39
34
|
Detected: #{node_package_version.raw}
|
40
35
|
gem: #{gem_version}
|
41
36
|
Ensure the installed version of the gem is the same as the version of
|
42
|
-
your installed
|
43
|
-
Do not use
|
37
|
+
your installed Node package. Do not use >= or ~> in your Gemfile for react_on_rails.
|
38
|
+
Do not use ^, ~, or other non-exact versions in your package.json for react-on-rails.
|
44
39
|
Run `yarn add react-on-rails --exact` in the directory containing folder node_modules.
|
45
40
|
MSG
|
46
41
|
end
|
47
42
|
|
48
43
|
def log_differing_versions_warning
|
49
|
-
msg = "**WARNING** ReactOnRails: ReactOnRails gem and
|
44
|
+
msg = "**WARNING** ReactOnRails: ReactOnRails gem and Node package versions do not match\n#{common_error_msg}"
|
50
45
|
Rails.logger.warn(msg)
|
51
46
|
end
|
52
47
|
|
53
48
|
def log_node_semver_version_warning
|
54
|
-
msg = "**WARNING** ReactOnRails: Your
|
55
|
-
"
|
49
|
+
msg = "**WARNING** ReactOnRails: Your Node package version for react-on-rails is not an exact version\n" \
|
50
|
+
"#{common_error_msg}"
|
56
51
|
Rails.logger.warn(msg)
|
57
52
|
end
|
58
53
|
|
@@ -60,9 +55,8 @@ module ReactOnRails
|
|
60
55
|
ReactOnRails::VERSION
|
61
56
|
end
|
62
57
|
|
63
|
-
def
|
64
|
-
|
65
|
-
[match[1], match[2], match[3]]
|
58
|
+
def gem_version_parts
|
59
|
+
gem_version.match(VERSION_PARTS_REGEX)&.captures&.compact
|
66
60
|
end
|
67
61
|
|
68
62
|
class NodePackageVersion
|
@@ -100,7 +94,7 @@ module ReactOnRails
|
|
100
94
|
# See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
|
101
95
|
# We want to disallow all expressions other than exact versions
|
102
96
|
# and the ones allowed by local_path_or_url?
|
103
|
-
raw.blank? || raw.
|
97
|
+
raw.blank? || raw.start_with?(/[~^><*]/) || raw.include?(" - ") || raw.include?(" || ")
|
104
98
|
end
|
105
99
|
|
106
100
|
def local_path_or_url?
|
@@ -110,15 +104,15 @@ module ReactOnRails
|
|
110
104
|
!raw.nil? && raw.include?("/") && !raw.start_with?("npm:")
|
111
105
|
end
|
112
106
|
|
113
|
-
def
|
107
|
+
def parts
|
114
108
|
return if local_path_or_url?
|
115
109
|
|
116
|
-
match = raw.match(
|
110
|
+
match = raw.match(VERSION_PARTS_REGEX)
|
117
111
|
unless match
|
118
112
|
raise ReactOnRails::Error, "Cannot parse version number '#{raw}' (only exact versions are supported)"
|
119
113
|
end
|
120
114
|
|
121
|
-
|
115
|
+
match.captures.compact
|
122
116
|
end
|
123
117
|
|
124
118
|
private
|
@@ -5,7 +5,7 @@ require_relative "version"
|
|
5
5
|
module ReactOnRails
|
6
6
|
class VersionSyntaxConverter
|
7
7
|
def rubygem_to_npm(rubygem_version = ReactOnRails::VERSION)
|
8
|
-
regex_match = rubygem_version.match(/(\d+\.\d+\.\d+)[
|
8
|
+
regex_match = rubygem_version.match(/(\d+\.\d+\.\d+)[.-]?(.+)?/)
|
9
9
|
return "#{regex_match[1]}-#{regex_match[2]}" if regex_match[2]
|
10
10
|
|
11
11
|
regex_match[1].to_s
|
data/lib/react_on_rails.rb
CHANGED
data/lib/tasks/assets.rake
CHANGED
@@ -26,7 +26,7 @@ namespace :react_on_rails do
|
|
26
26
|
else
|
27
27
|
# Left in this warning message in case this rake task is run directly
|
28
28
|
msg = <<~MSG
|
29
|
-
React on Rails is aborting
|
29
|
+
React on Rails is aborting Webpack compilation from task react_on_rails:assets:webpack
|
30
30
|
because you do not have the `config.build_production_command` defined.
|
31
31
|
MSG
|
32
32
|
puts Rainbow(msg).red
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../react_on_rails"
|
4
|
+
require_relative "../react_on_rails/doctor"
|
5
|
+
|
6
|
+
begin
|
7
|
+
require "rainbow"
|
8
|
+
rescue LoadError
|
9
|
+
# Fallback if Rainbow is not available
|
10
|
+
class Rainbow
|
11
|
+
def self.method_missing(_method, text)
|
12
|
+
SimpleColorWrapper.new(text)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.respond_to_missing?(_method, _include_private = false)
|
16
|
+
true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class SimpleColorWrapper
|
21
|
+
def initialize(text)
|
22
|
+
@text = text
|
23
|
+
end
|
24
|
+
|
25
|
+
def method_missing(_method, *_args)
|
26
|
+
self
|
27
|
+
end
|
28
|
+
|
29
|
+
def respond_to_missing?(_method, _include_private = false)
|
30
|
+
true
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
@text
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace :react_on_rails do
|
40
|
+
desc "Diagnose React on Rails setup and configuration"
|
41
|
+
task :doctor do
|
42
|
+
verbose = ENV["VERBOSE"] == "true"
|
43
|
+
fix = ENV["FIX"] == "true"
|
44
|
+
|
45
|
+
doctor = ReactOnRails::Doctor.new(verbose: verbose, fix: fix)
|
46
|
+
doctor.run_diagnosis
|
47
|
+
end
|
48
|
+
end
|
@@ -1,11 +1,168 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
# rubocop:disable Metrics/BlockLength
|
3
4
|
namespace :react_on_rails do
|
4
5
|
desc <<~DESC
|
5
6
|
If there is a file inside any directory matching config.components_subdirectory, this command generates corresponding packs.
|
7
|
+
|
8
|
+
This task will:
|
9
|
+
- Clean out existing generated directories (javascript/generated and javascript/packs/generated)
|
10
|
+
- List all files being deleted for transparency
|
11
|
+
- Generate new pack files for discovered React components
|
12
|
+
- Skip generation if files are already up to date
|
13
|
+
|
14
|
+
Generated directories:
|
15
|
+
- app/javascript/packs/generated/ (client pack files)
|
16
|
+
- app/javascript/generated/ (server bundle files)
|
6
17
|
DESC
|
7
18
|
|
8
19
|
task generate_packs: :environment do
|
9
|
-
|
20
|
+
puts Rainbow("🚀 Starting React on Rails pack generation...").bold
|
21
|
+
puts Rainbow("📁 Auto-load bundle: #{ReactOnRails.configuration.auto_load_bundle}").cyan
|
22
|
+
puts Rainbow("📂 Components subdirectory: #{ReactOnRails.configuration.components_subdirectory}").cyan
|
23
|
+
puts ""
|
24
|
+
|
25
|
+
begin
|
26
|
+
start_time = Time.now
|
27
|
+
ReactOnRails::PacksGenerator.instance.generate_packs_if_stale
|
28
|
+
end_time = Time.now
|
29
|
+
|
30
|
+
puts ""
|
31
|
+
puts Rainbow("✨ Pack generation completed in #{((end_time - start_time) * 1000).round(1)}ms").green
|
32
|
+
rescue ReactOnRails::Error => e
|
33
|
+
handle_react_on_rails_error(e)
|
34
|
+
exit 1
|
35
|
+
rescue StandardError => e
|
36
|
+
handle_standard_error(e)
|
37
|
+
exit 1
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
# rubocop:disable Metrics/AbcSize
|
44
|
+
def handle_react_on_rails_error(error)
|
45
|
+
puts ""
|
46
|
+
puts Rainbow("❌ REACT ON RAILS ERROR").red.bold
|
47
|
+
puts Rainbow("=" * 80).red
|
48
|
+
puts Rainbow("🚨 Pack generation failed with the following error:").red
|
49
|
+
puts ""
|
50
|
+
puts Rainbow("📋 ERROR DETAILS:").yellow
|
51
|
+
puts Rainbow(" Type: #{error.class.name}").white
|
52
|
+
puts Rainbow(" Message: #{error.message}").white
|
53
|
+
puts ""
|
54
|
+
|
55
|
+
highlight_main_error(error)
|
56
|
+
show_common_solutions(error)
|
57
|
+
show_debugging_steps
|
58
|
+
show_documentation_links
|
59
|
+
end
|
60
|
+
# rubocop:enable Metrics/AbcSize
|
61
|
+
|
62
|
+
def highlight_main_error(error)
|
63
|
+
return unless error.message.include?("**ERROR**")
|
64
|
+
|
65
|
+
error_lines = error.message.split("\n")
|
66
|
+
error_lines.each do |line|
|
67
|
+
next unless line.include?("**ERROR**")
|
68
|
+
|
69
|
+
puts Rainbow("🔥 MAIN ISSUE:").red.bold
|
70
|
+
puts Rainbow(" #{line.gsub('**ERROR**', '').strip}").yellow
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# rubocop:disable Metrics/AbcSize
|
75
|
+
def show_common_solutions(error)
|
76
|
+
puts ""
|
77
|
+
puts Rainbow("💡 COMMON SOLUTIONS:").green.bold
|
78
|
+
|
79
|
+
case error.message
|
80
|
+
when /client specific definition.*overrides the common definition/
|
81
|
+
puts Rainbow(" • You have both common and client/server specific component files").white
|
82
|
+
puts Rainbow(" • Delete the common component file (e.g., Component.jsx)").white
|
83
|
+
puts Rainbow(" • Keep only the client/server specific files " \
|
84
|
+
"(Component.client.jsx, Component.server.jsx)").white
|
85
|
+
puts Rainbow(" • See: https://www.shakacode.com/react-on-rails/docs/guides/" \
|
86
|
+
"auto-bundling-file-system-based-automated-bundle-generation.md").cyan
|
87
|
+
|
88
|
+
when /Cannot find component/
|
89
|
+
puts Rainbow(" • Check that your component file exists in the expected location").white
|
90
|
+
puts Rainbow(" • Verify the component is exported as default export").white
|
91
|
+
puts Rainbow(" • Ensure the file extension is .jsx or .js").white
|
92
|
+
|
93
|
+
when /CSS module.*not found/
|
94
|
+
puts Rainbow(" • Check that the CSS module file exists").white
|
95
|
+
puts Rainbow(" • Verify the import path is correct").white
|
96
|
+
puts Rainbow(" • Ensure all CSS classes referenced in the component exist").white
|
97
|
+
|
98
|
+
else
|
99
|
+
puts Rainbow(" • Check component file structure and naming").white
|
100
|
+
puts Rainbow(" • Verify all imports and exports are correct").white
|
101
|
+
puts Rainbow(" • Run with --trace for more detailed error information").white
|
102
|
+
end
|
103
|
+
end
|
104
|
+
# rubocop:enable Metrics/AbcSize
|
105
|
+
|
106
|
+
def show_debugging_steps
|
107
|
+
puts ""
|
108
|
+
puts Rainbow("🔧 DEBUGGING STEPS:").blue.bold
|
109
|
+
components_path = "app/javascript/src/**/#{ReactOnRails.configuration.components_subdirectory}/"
|
110
|
+
puts Rainbow(" 1. Check component files in: #{components_path}").white
|
111
|
+
puts Rainbow(" 2. Verify component exports: export default ComponentName").white
|
112
|
+
puts Rainbow(" 3. Check for conflicting common/client/server files").white
|
113
|
+
puts Rainbow(" 4. Run: rake react_on_rails:generate_packs --trace").white
|
114
|
+
puts Rainbow(" 5. Check Rails logs for additional details").white
|
115
|
+
end
|
116
|
+
|
117
|
+
def show_documentation_links
|
118
|
+
puts ""
|
119
|
+
puts Rainbow("📚 DOCUMENTATION:").magenta.bold
|
120
|
+
puts Rainbow(" • File-system based components: https://www.shakacode.com/react-on-rails/docs/" \
|
121
|
+
"guides/auto-bundling-file-system-based-automated-bundle-generation.md").cyan
|
122
|
+
puts Rainbow(" • Component registration: https://www.shakacode.com/react-on-rails/docs/").cyan
|
123
|
+
puts Rainbow("=" * 80).red
|
124
|
+
end
|
125
|
+
|
126
|
+
def show_help_and_support
|
127
|
+
puts ""
|
128
|
+
troubleshooting_content = ReactOnRails::Utils.default_troubleshooting_section
|
129
|
+
# Display the troubleshooting content with color formatting
|
130
|
+
troubleshooting_content.split("\n").each do |line|
|
131
|
+
case line
|
132
|
+
when /^📞/
|
133
|
+
puts Rainbow(line).magenta.bold
|
134
|
+
when /^\s*•\s*🚀/
|
135
|
+
puts Rainbow(line).yellow
|
136
|
+
when /^\s*•/
|
137
|
+
puts Rainbow(line).cyan
|
138
|
+
else
|
139
|
+
puts Rainbow(line).white unless line.strip.empty?
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
# rubocop:disable Metrics/AbcSize
|
145
|
+
def handle_standard_error(error)
|
146
|
+
puts ""
|
147
|
+
puts Rainbow("❌ UNEXPECTED ERROR").red.bold
|
148
|
+
puts Rainbow("=" * 80).red
|
149
|
+
puts Rainbow("🚨 An unexpected error occurred during pack generation:").red
|
150
|
+
puts ""
|
151
|
+
puts Rainbow("📋 ERROR DETAILS:").yellow
|
152
|
+
puts Rainbow(" Type: #{error.class.name}").white
|
153
|
+
puts Rainbow(" Message: #{error.message}").white
|
154
|
+
puts Rainbow(" Backtrace:").white
|
155
|
+
error.backtrace.first(10).each { |line| puts Rainbow(" #{line}").white }
|
156
|
+
puts Rainbow(" ... (run with --trace for full backtrace)").white
|
157
|
+
puts ""
|
158
|
+
puts Rainbow("🔧 DEBUGGING STEPS:").blue.bold
|
159
|
+
puts Rainbow(" 1. Run: rake react_on_rails:generate_packs --trace").white
|
160
|
+
puts Rainbow(" 2. Check Rails logs: tail -f log/development.log").white
|
161
|
+
puts Rainbow(" 3. Verify all dependencies are installed: bundle install && npm install").white
|
162
|
+
puts Rainbow(" 4. Clear cache: rm -rf tmp/cache").white
|
163
|
+
show_help_and_support
|
164
|
+
puts Rainbow("=" * 80).red
|
10
165
|
end
|
166
|
+
# rubocop:enable Metrics/AbcSize
|
11
167
|
end
|
168
|
+
# rubocop:enable Metrics/BlockLength
|
data/react_on_rails.gemspec
CHANGED
@@ -31,6 +31,7 @@ Gem::Specification.new do |s|
|
|
31
31
|
s.add_dependency "execjs", "~> 2.5"
|
32
32
|
s.add_dependency "rails", ">= 5.2"
|
33
33
|
s.add_dependency "rainbow", "~> 3.0"
|
34
|
+
s.add_dependency "shakapacker", ">= 6.0"
|
34
35
|
|
35
36
|
s.add_development_dependency "gem-release"
|
36
37
|
s.post_install_message = '
|
data/tsconfig.json
CHANGED
@@ -6,12 +6,14 @@
|
|
6
6
|
// needed for Jest tests even though we don't use .tsx
|
7
7
|
"jsx": "react-jsx",
|
8
8
|
"lib": ["dom", "es2020"],
|
9
|
-
"module": "node16",
|
10
9
|
"noImplicitAny": true,
|
11
10
|
"outDir": "node_package/lib",
|
11
|
+
"allowImportingTsExtensions": true,
|
12
|
+
"rewriteRelativeImportExtensions": true,
|
12
13
|
"strict": true,
|
13
14
|
"incremental": true,
|
14
|
-
"target": "es2020"
|
15
|
+
"target": "es2020",
|
16
|
+
"typeRoots": ["./node_modules/@types", "./node_package/types"]
|
15
17
|
},
|
16
|
-
"include": ["node_package/src/**/*"]
|
18
|
+
"include": ["node_package/src/**/*", "node_package/types/**/*"]
|
17
19
|
}
|