react_on_rails 16.1.2 → 16.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/.rspec +2 -0
- data/.rubocop.yml +85 -0
- data/Gemfile.development_dependencies +8 -7
- data/Gemfile.lock +158 -119
- data/Steepfile +56 -0
- data/lib/generators/react_on_rails/base_generator.rb +43 -120
- data/lib/generators/react_on_rails/dev_tests_generator.rb +2 -1
- data/lib/generators/react_on_rails/generator_helper.rb +102 -2
- data/lib/generators/react_on_rails/install_generator.rb +36 -156
- data/lib/generators/react_on_rails/js_dependency_manager.rb +383 -0
- data/lib/generators/react_on_rails/templates/base/base/.dev-services.yml.example +76 -0
- data/lib/generators/react_on_rails/templates/base/base/bin/shakapacker-precompile-hook +30 -0
- data/lib/generators/react_on_rails/templates/base/base/bin/switch-bundler +141 -0
- data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +44 -45
- data/lib/generators/react_on_rails/templates/base/base/config/{shakapacker.yml → shakapacker.yml.tt} +28 -3
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +15 -9
- data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +42 -6
- data/lib/react_on_rails/configuration.rb +149 -32
- data/lib/react_on_rails/controller.rb +3 -3
- data/lib/react_on_rails/dev/pack_generator.rb +168 -2
- data/lib/react_on_rails/dev/process_manager.rb +136 -14
- data/lib/react_on_rails/dev/server_manager.rb +194 -26
- data/lib/react_on_rails/dev/service_checker.rb +200 -0
- data/lib/react_on_rails/doctor.rb +341 -12
- data/lib/react_on_rails/engine.rb +75 -1
- data/lib/react_on_rails/git_utils.rb +3 -1
- data/lib/react_on_rails/helper.rb +70 -192
- data/lib/react_on_rails/locales/base.rb +17 -5
- data/lib/react_on_rails/packer_utils.rb +79 -2
- data/lib/react_on_rails/packs_generator.rb +57 -39
- data/lib/react_on_rails/prerender_error.rb +74 -17
- data/lib/react_on_rails/pro_helper.rb +64 -0
- data/lib/react_on_rails/react_component/render_options.rb +7 -7
- data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +2 -5
- data/lib/react_on_rails/smart_error.rb +326 -0
- data/lib/react_on_rails/system_checker.rb +8 -9
- data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +16 -7
- data/lib/react_on_rails/utils.rb +241 -55
- data/lib/react_on_rails/version.rb +1 -1
- data/lib/react_on_rails/version_checker.rb +383 -35
- data/lib/tasks/generate_packs.rake +12 -6
- data/lib/tasks/locale.rake +6 -1
- data/rakelib/docker.rake +26 -0
- data/rakelib/dummy_apps.rake +30 -0
- data/rakelib/example_type.rb +121 -0
- data/rakelib/examples_config.yml +52 -0
- data/rakelib/lint.rake +52 -0
- data/rakelib/node_package.rake +15 -0
- data/rakelib/rbs.rake +70 -0
- data/rakelib/run_rspec.rake +223 -0
- data/rakelib/shakapacker_examples.rake +171 -0
- data/rakelib/task_helpers.rb +134 -0
- data/rakelib/update_changelog.rake +73 -0
- data/react_on_rails.gemspec +4 -3
- data/sig/README.md +52 -0
- data/sig/react_on_rails/configuration.rbs +96 -0
- data/sig/react_on_rails/controller.rbs +15 -0
- data/sig/react_on_rails/dev/file_manager.rbs +15 -0
- data/sig/react_on_rails/dev/pack_generator.rbs +19 -0
- data/sig/react_on_rails/dev/process_manager.rbs +22 -0
- data/sig/react_on_rails/dev/server_manager.rbs +39 -0
- data/sig/react_on_rails/dev/service_checker.rbs +22 -0
- data/sig/react_on_rails/error.rbs +4 -0
- data/sig/react_on_rails/generators/js_dependency_manager.rbs +123 -0
- data/sig/react_on_rails/git_utils.rbs +8 -0
- data/sig/react_on_rails/helper.rbs +65 -0
- data/sig/react_on_rails/json_parse_error.rbs +10 -0
- data/sig/react_on_rails/locales.rbs +46 -0
- data/sig/react_on_rails/packer_utils.rbs +15 -0
- data/sig/react_on_rails/prerender_error.rbs +21 -0
- data/sig/react_on_rails/server_rendering_pool.rbs +12 -0
- data/sig/react_on_rails/smart_error.rbs +28 -0
- data/sig/react_on_rails/test_helper.rbs +11 -0
- data/sig/react_on_rails/utils.rbs +34 -0
- data/sig/react_on_rails/version_checker.rbs +12 -0
- data/sig/react_on_rails.rbs +17 -0
- metadata +49 -32
- data/AI_AGENT_INSTRUCTIONS.md +0 -63
- data/CHANGELOG.md +0 -1836
- data/CLAUDE.md +0 -135
- data/CODING_AGENTS.md +0 -313
- data/CONTRIBUTING.md +0 -668
- data/Dockerfile_tests +0 -12
- data/KUDOS.md +0 -114
- data/LICENSE.md +0 -47
- data/LICENSES/README.md +0 -14
- data/NEWS.md +0 -62
- data/PROJECTS.md +0 -63
- data/REACT-ON-RAILS-PRO-LICENSE.md +0 -129
- data/README.md +0 -217
- data/SUMMARY.md +0 -88
- data/TODO.md +0 -135
- data/bin/lefthook/check-trailing-newlines +0 -38
- data/bin/lefthook/get-changed-files +0 -26
- data/bin/lefthook/prettier-format +0 -26
- data/bin/lefthook/ruby-autofix +0 -26
- data/bin/lefthook/ruby-lint +0 -27
- data/docker-compose.yml +0 -11
- data/eslint.config.ts +0 -232
- data/knip.ts +0 -114
- data/lib/react_on_rails/pro/NOTICE +0 -21
- data/lib/react_on_rails/pro/helper.rb +0 -122
- data/lib/react_on_rails/pro/utils.rb +0 -53
- data/tsconfig.eslint.json +0 -6
- data/tsconfig.json +0 -19
|
@@ -17,38 +17,187 @@ module ReactOnRails
|
|
|
17
17
|
@node_package_version = node_package_version
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
#
|
|
21
|
-
#
|
|
22
|
-
#
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
# Validates version and package compatibility.
|
|
21
|
+
# Raises ReactOnRails::Error if:
|
|
22
|
+
# - package.json file is not found
|
|
23
|
+
# - Both react-on-rails and react-on-rails-pro packages are installed
|
|
24
|
+
# - Pro gem is installed but using react-on-rails package
|
|
25
|
+
# - Pro package is installed but Pro gem is not installed
|
|
26
|
+
# - Non-exact version is used
|
|
27
|
+
# - Versions don't match
|
|
28
|
+
def validate_version_and_package_compatibility!
|
|
29
|
+
validate_package_json_exists!
|
|
30
|
+
validate_package_gem_compatibility!
|
|
31
|
+
validate_exact_version!
|
|
32
|
+
validate_version_match!
|
|
28
33
|
end
|
|
29
34
|
|
|
30
35
|
private
|
|
31
36
|
|
|
32
|
-
def
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
def validate_package_json_exists!
|
|
38
|
+
return if File.exist?(node_package_version.package_json)
|
|
39
|
+
|
|
40
|
+
base_install_cmd = ReactOnRails::Utils.package_manager_install_exact_command("react-on-rails", gem_version)
|
|
41
|
+
pro_install_cmd = ReactOnRails::Utils.package_manager_install_exact_command("react-on-rails-pro", gem_version)
|
|
42
|
+
|
|
43
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
44
|
+
**ERROR** ReactOnRails: package.json file not found.
|
|
45
|
+
|
|
46
|
+
Expected location: #{node_package_version.package_json}
|
|
47
|
+
|
|
48
|
+
React on Rails requires a package.json file with either 'react-on-rails' or
|
|
49
|
+
'react-on-rails-pro' package installed.
|
|
50
|
+
|
|
51
|
+
Fix:
|
|
52
|
+
1. Ensure you have a package.json in your project root
|
|
53
|
+
2. Run: #{base_install_cmd}
|
|
54
|
+
|
|
55
|
+
Or if using React on Rails Pro:
|
|
56
|
+
Run: #{pro_install_cmd}
|
|
40
57
|
MSG
|
|
41
58
|
end
|
|
42
59
|
|
|
43
|
-
def
|
|
44
|
-
|
|
45
|
-
|
|
60
|
+
def validate_package_gem_compatibility!
|
|
61
|
+
has_base_package = node_package_version.react_on_rails_package?
|
|
62
|
+
has_pro_package = node_package_version.react_on_rails_pro_package?
|
|
63
|
+
is_pro_gem = ReactOnRails::Utils.react_on_rails_pro?
|
|
64
|
+
|
|
65
|
+
validate_packages_installed!(has_base_package, has_pro_package)
|
|
66
|
+
validate_no_duplicate_packages!(has_base_package, has_pro_package)
|
|
67
|
+
validate_pro_gem_uses_pro_package!(is_pro_gem, has_pro_package)
|
|
68
|
+
validate_pro_package_has_pro_gem!(is_pro_gem, has_pro_package)
|
|
46
69
|
end
|
|
47
70
|
|
|
48
|
-
def
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
71
|
+
def validate_packages_installed!(has_base_package, has_pro_package)
|
|
72
|
+
return if has_base_package || has_pro_package
|
|
73
|
+
|
|
74
|
+
base_install_cmd = ReactOnRails::Utils.package_manager_install_exact_command("react-on-rails", gem_version)
|
|
75
|
+
pro_install_cmd = ReactOnRails::Utils.package_manager_install_exact_command("react-on-rails-pro", gem_version)
|
|
76
|
+
|
|
77
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
78
|
+
**ERROR** ReactOnRails: No React on Rails npm package is installed.
|
|
79
|
+
|
|
80
|
+
You must install either 'react-on-rails' or 'react-on-rails-pro' package.
|
|
81
|
+
|
|
82
|
+
Fix:
|
|
83
|
+
If using the standard (free) version:
|
|
84
|
+
Run: #{base_install_cmd}
|
|
85
|
+
|
|
86
|
+
Or if using React on Rails Pro:
|
|
87
|
+
Run: #{pro_install_cmd}
|
|
88
|
+
|
|
89
|
+
#{package_json_location}
|
|
90
|
+
MSG
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def validate_no_duplicate_packages!(has_base_package, has_pro_package)
|
|
94
|
+
return unless has_base_package && has_pro_package
|
|
95
|
+
|
|
96
|
+
remove_cmd = ReactOnRails::Utils.package_manager_remove_command("react-on-rails")
|
|
97
|
+
|
|
98
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
99
|
+
**ERROR** ReactOnRails: Both 'react-on-rails' and 'react-on-rails-pro' packages are installed.
|
|
100
|
+
|
|
101
|
+
If you're using React on Rails Pro, only install the 'react-on-rails-pro' package.
|
|
102
|
+
The Pro package already includes all functionality from the base package.
|
|
103
|
+
|
|
104
|
+
Fix:
|
|
105
|
+
1. Remove 'react-on-rails' from your package.json dependencies
|
|
106
|
+
2. Run: #{remove_cmd}
|
|
107
|
+
3. Keep only: react-on-rails-pro
|
|
108
|
+
|
|
109
|
+
#{package_json_location}
|
|
110
|
+
MSG
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def validate_pro_gem_uses_pro_package!(is_pro_gem, has_pro_package)
|
|
114
|
+
return unless is_pro_gem && !has_pro_package
|
|
115
|
+
|
|
116
|
+
remove_cmd = ReactOnRails::Utils.package_manager_remove_command("react-on-rails")
|
|
117
|
+
install_cmd = ReactOnRails::Utils.package_manager_install_exact_command("react-on-rails-pro", gem_version)
|
|
118
|
+
|
|
119
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
120
|
+
**ERROR** ReactOnRails: You have the Pro gem installed but are using the base 'react-on-rails' package.
|
|
121
|
+
|
|
122
|
+
When using React on Rails Pro, you must use the 'react-on-rails-pro' npm package.
|
|
123
|
+
|
|
124
|
+
Fix:
|
|
125
|
+
1. Remove the base package: #{remove_cmd}
|
|
126
|
+
2. Install the Pro package: #{install_cmd}
|
|
127
|
+
|
|
128
|
+
#{package_json_location}
|
|
129
|
+
MSG
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def validate_pro_package_has_pro_gem!(is_pro_gem, has_pro_package)
|
|
133
|
+
return unless !is_pro_gem && has_pro_package
|
|
134
|
+
|
|
135
|
+
remove_pro_cmd = ReactOnRails::Utils.package_manager_remove_command("react-on-rails-pro")
|
|
136
|
+
install_base_cmd = ReactOnRails::Utils.package_manager_install_exact_command("react-on-rails", gem_version)
|
|
137
|
+
|
|
138
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
139
|
+
**ERROR** ReactOnRails: You have the 'react-on-rails-pro' package installed but the Pro gem is not installed.
|
|
140
|
+
|
|
141
|
+
The Pro npm package requires the Pro gem to function.
|
|
142
|
+
|
|
143
|
+
Fix:
|
|
144
|
+
1. Install the Pro gem by adding to your Gemfile:
|
|
145
|
+
gem 'react_on_rails_pro'
|
|
146
|
+
2. Run: bundle install
|
|
147
|
+
|
|
148
|
+
Or if you meant to use the base version:
|
|
149
|
+
1. Remove the Pro package: #{remove_pro_cmd}
|
|
150
|
+
2. Install the base package: #{install_base_cmd}
|
|
151
|
+
|
|
152
|
+
#{package_json_location}
|
|
153
|
+
MSG
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def validate_exact_version!
|
|
157
|
+
return if node_package_version.raw.nil? || node_package_version.local_path_or_url?
|
|
158
|
+
|
|
159
|
+
return unless node_package_version.semver_wildcard?
|
|
160
|
+
|
|
161
|
+
package_name = node_package_version.package_name
|
|
162
|
+
install_cmd = ReactOnRails::Utils.package_manager_install_exact_command(package_name, gem_version)
|
|
163
|
+
|
|
164
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
165
|
+
**ERROR** ReactOnRails: The '#{package_name}' package version is not an exact version.
|
|
166
|
+
|
|
167
|
+
Detected: #{node_package_version.raw}
|
|
168
|
+
Gem: #{gem_version}
|
|
169
|
+
|
|
170
|
+
React on Rails requires exact version matching between the gem and npm package.
|
|
171
|
+
Do not use ^, ~, >, <, *, or other semver ranges.
|
|
172
|
+
|
|
173
|
+
Fix:
|
|
174
|
+
Run: #{install_cmd}
|
|
175
|
+
|
|
176
|
+
#{package_json_location}
|
|
177
|
+
MSG
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
def validate_version_match!
|
|
181
|
+
return if node_package_version.raw.nil? || node_package_version.local_path_or_url?
|
|
182
|
+
|
|
183
|
+
return if node_package_version.parts == gem_version_parts
|
|
184
|
+
|
|
185
|
+
package_name = node_package_version.package_name
|
|
186
|
+
install_cmd = ReactOnRails::Utils.package_manager_install_exact_command(package_name, gem_version)
|
|
187
|
+
|
|
188
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
189
|
+
**ERROR** ReactOnRails: The '#{package_name}' package version does not match the gem version.
|
|
190
|
+
|
|
191
|
+
Package: #{node_package_version.raw}
|
|
192
|
+
Gem: #{gem_version}
|
|
193
|
+
|
|
194
|
+
The npm package and gem versions must match exactly for compatibility.
|
|
195
|
+
|
|
196
|
+
Fix:
|
|
197
|
+
Run: #{install_cmd}
|
|
198
|
+
|
|
199
|
+
#{package_json_location}
|
|
200
|
+
MSG
|
|
52
201
|
end
|
|
53
202
|
|
|
54
203
|
def gem_version
|
|
@@ -59,42 +208,113 @@ module ReactOnRails
|
|
|
59
208
|
gem_version.match(VERSION_PARTS_REGEX)&.captures&.compact
|
|
60
209
|
end
|
|
61
210
|
|
|
211
|
+
def package_json_location
|
|
212
|
+
"Package.json location: #{VersionChecker::NodePackageVersion.package_json_path}"
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
# rubocop:disable Metrics/ClassLength
|
|
62
216
|
class NodePackageVersion
|
|
63
|
-
attr_reader :package_json
|
|
217
|
+
attr_reader :package_json, :yarn_lock, :package_lock
|
|
64
218
|
|
|
65
219
|
def self.build
|
|
66
|
-
new(package_json_path)
|
|
220
|
+
new(package_json_path, yarn_lock_path, package_lock_path)
|
|
67
221
|
end
|
|
68
222
|
|
|
69
223
|
def self.package_json_path
|
|
70
224
|
Rails.root.join(ReactOnRails.configuration.node_modules_location, "package.json")
|
|
71
225
|
end
|
|
72
226
|
|
|
73
|
-
def
|
|
227
|
+
def self.yarn_lock_path
|
|
228
|
+
# Lockfiles are in the same directory as package.json
|
|
229
|
+
# If node_modules_location is empty, use Rails.root
|
|
230
|
+
base_dir = ReactOnRails.configuration.node_modules_location.presence || ""
|
|
231
|
+
Rails.root.join(base_dir, "yarn.lock").to_s
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
def self.package_lock_path
|
|
235
|
+
# Lockfiles are in the same directory as package.json
|
|
236
|
+
# If node_modules_location is empty, use Rails.root
|
|
237
|
+
base_dir = ReactOnRails.configuration.node_modules_location.presence || ""
|
|
238
|
+
Rails.root.join(base_dir, "package-lock.json").to_s
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
def initialize(package_json, yarn_lock = nil, package_lock = nil)
|
|
74
242
|
@package_json = package_json
|
|
243
|
+
@yarn_lock = yarn_lock
|
|
244
|
+
@package_lock = package_lock
|
|
75
245
|
end
|
|
76
246
|
|
|
77
247
|
def raw
|
|
78
248
|
return @raw if defined?(@raw)
|
|
79
249
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
250
|
+
return @raw = nil unless File.exist?(package_json)
|
|
251
|
+
|
|
252
|
+
parsed = parsed_package_contents
|
|
253
|
+
return @raw = nil unless parsed.key?("dependencies")
|
|
254
|
+
|
|
255
|
+
deps = parsed["dependencies"]
|
|
256
|
+
|
|
257
|
+
# Check for react-on-rails-pro first (Pro takes precedence)
|
|
258
|
+
if deps.key?("react-on-rails-pro")
|
|
259
|
+
@raw = resolve_version(deps["react-on-rails-pro"], "react-on-rails-pro")
|
|
260
|
+
return @raw
|
|
86
261
|
end
|
|
87
|
-
|
|
88
|
-
|
|
262
|
+
|
|
263
|
+
# Fall back to react-on-rails
|
|
264
|
+
if deps.key?("react-on-rails")
|
|
265
|
+
@raw = resolve_version(deps["react-on-rails"], "react-on-rails")
|
|
266
|
+
return @raw
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Neither package found
|
|
270
|
+
msg = "No 'react-on-rails' or 'react-on-rails-pro' entry in the dependencies of " \
|
|
271
|
+
"#{NodePackageVersion.package_json_path}, which is the expected location according to " \
|
|
272
|
+
"ReactOnRails.configuration.node_modules_location"
|
|
89
273
|
Rails.logger.warn(msg)
|
|
90
274
|
@raw = nil
|
|
91
275
|
end
|
|
92
276
|
|
|
277
|
+
def react_on_rails_package?
|
|
278
|
+
package_installed?("react-on-rails")
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def react_on_rails_pro_package?
|
|
282
|
+
package_installed?("react-on-rails-pro")
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def package_name
|
|
286
|
+
return "react-on-rails-pro" if react_on_rails_pro_package?
|
|
287
|
+
|
|
288
|
+
"react-on-rails"
|
|
289
|
+
end
|
|
290
|
+
|
|
93
291
|
def semver_wildcard?
|
|
94
292
|
# See https://docs.npmjs.com/cli/v10/configuring-npm/package-json#dependencies
|
|
95
293
|
# We want to disallow all expressions other than exact versions
|
|
96
294
|
# and the ones allowed by local_path_or_url?
|
|
97
|
-
|
|
295
|
+
return true if raw.blank?
|
|
296
|
+
|
|
297
|
+
special_version_string? || wildcard_or_x_range? || range_operator? || range_syntax?
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
def special_version_string?
|
|
301
|
+
%w[latest next canary beta alpha rc].include?(raw.downcase)
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def wildcard_or_x_range?
|
|
305
|
+
raw == "*" ||
|
|
306
|
+
raw =~ /^[xX*]$/ ||
|
|
307
|
+
raw =~ /^[xX*]\./ ||
|
|
308
|
+
raw =~ /\.[xX*]\b/ ||
|
|
309
|
+
raw =~ /\.[xX*]$/
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
def range_operator?
|
|
313
|
+
raw.start_with?(/[~^><*]/)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
def range_syntax?
|
|
317
|
+
raw.include?(" - ") || raw.include?(" || ")
|
|
98
318
|
end
|
|
99
319
|
|
|
100
320
|
def local_path_or_url?
|
|
@@ -117,9 +337,137 @@ module ReactOnRails
|
|
|
117
337
|
|
|
118
338
|
private
|
|
119
339
|
|
|
340
|
+
# Resolve version from lockfiles if available, otherwise use package.json version
|
|
341
|
+
def resolve_version(package_json_version, package_name)
|
|
342
|
+
# If package.json specifies a local path or URL, don't try to resolve from lockfiles
|
|
343
|
+
# Lockfiles may contain placeholder versions like "0.0.0" for local links
|
|
344
|
+
return package_json_version if local_path_or_url_version?(package_json_version)
|
|
345
|
+
|
|
346
|
+
# Try yarn.lock first
|
|
347
|
+
if yarn_lock && File.exist?(yarn_lock)
|
|
348
|
+
lockfile_version = version_from_yarn_lock(package_name)
|
|
349
|
+
return lockfile_version if lockfile_version
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
# Try package-lock.json
|
|
353
|
+
if package_lock && File.exist?(package_lock)
|
|
354
|
+
lockfile_version = version_from_package_lock(package_name)
|
|
355
|
+
return lockfile_version if lockfile_version
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
# Fall back to package.json version
|
|
359
|
+
package_json_version
|
|
360
|
+
end
|
|
361
|
+
|
|
362
|
+
# Check if a version string represents a local path or URL
|
|
363
|
+
def local_path_or_url_version?(version)
|
|
364
|
+
return false if version.nil?
|
|
365
|
+
|
|
366
|
+
version.include?("/") && !version.start_with?("npm:")
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
# Parse version from yarn.lock
|
|
370
|
+
# Looks for entries like:
|
|
371
|
+
# react-on-rails@^16.1.1:
|
|
372
|
+
# version "16.1.1"
|
|
373
|
+
# The pattern ensures exact package name match to avoid matching similar names
|
|
374
|
+
# (e.g., "react-on-rails" won't match "react-on-rails-pro")
|
|
375
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
376
|
+
def version_from_yarn_lock(package_name)
|
|
377
|
+
return nil unless yarn_lock && File.exist?(yarn_lock)
|
|
378
|
+
|
|
379
|
+
in_package_block = false
|
|
380
|
+
File.foreach(yarn_lock) do |line|
|
|
381
|
+
# Check if we're starting the block for our package
|
|
382
|
+
# Pattern: optionally quoted package name, followed by @, ensuring it's not followed by more word chars
|
|
383
|
+
# This prevents "react-on-rails" from matching "react-on-rails-pro"
|
|
384
|
+
if line.match?(/^"?#{Regexp.escape(package_name)}@/)
|
|
385
|
+
in_package_block = true
|
|
386
|
+
next
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
# If we're in the package block, look for the version line
|
|
390
|
+
if in_package_block
|
|
391
|
+
# Version line looks like: version "16.1.1"
|
|
392
|
+
if (match = line.match(/^\s+version\s+"([^"]+)"/))
|
|
393
|
+
return match[1]
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
# If we hit a blank line or new package, we've left the block
|
|
397
|
+
break if line.strip.empty? || (line[0] != " " && line[0] != "\t")
|
|
398
|
+
end
|
|
399
|
+
end
|
|
400
|
+
|
|
401
|
+
nil
|
|
402
|
+
end
|
|
403
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
404
|
+
|
|
405
|
+
# Parse version from package-lock.json
|
|
406
|
+
# Supports both v1 (dependencies) and v2/v3 (packages) formats
|
|
407
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
408
|
+
def version_from_package_lock(package_name)
|
|
409
|
+
return nil unless package_lock && File.exist?(package_lock)
|
|
410
|
+
|
|
411
|
+
begin
|
|
412
|
+
parsed = JSON.parse(File.read(package_lock))
|
|
413
|
+
|
|
414
|
+
# Try v2/v3 format first (packages)
|
|
415
|
+
if parsed["packages"]
|
|
416
|
+
# Look for node_modules/package-name entry
|
|
417
|
+
node_modules_key = "node_modules/#{package_name}"
|
|
418
|
+
package_data = parsed["packages"][node_modules_key]
|
|
419
|
+
return package_data["version"] if package_data&.key?("version")
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
# Fall back to v1 format (dependencies)
|
|
423
|
+
if parsed["dependencies"]
|
|
424
|
+
dependency_data = parsed["dependencies"][package_name]
|
|
425
|
+
# In v1, the dependency can be a hash with a "version" key
|
|
426
|
+
return dependency_data["version"] if dependency_data.is_a?(Hash) && dependency_data.key?("version")
|
|
427
|
+
end
|
|
428
|
+
rescue JSON::ParserError
|
|
429
|
+
# If we can't parse the lockfile, fall back to package.json version
|
|
430
|
+
nil
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
nil
|
|
434
|
+
end
|
|
435
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
436
|
+
|
|
437
|
+
def package_installed?(package_name)
|
|
438
|
+
return false unless File.exist?(package_json)
|
|
439
|
+
|
|
440
|
+
parsed = parsed_package_contents
|
|
441
|
+
parsed.dig("dependencies", package_name).present?
|
|
442
|
+
end
|
|
443
|
+
|
|
120
444
|
def package_json_contents
|
|
121
445
|
@package_json_contents ||= File.read(package_json)
|
|
122
446
|
end
|
|
447
|
+
|
|
448
|
+
def parsed_package_contents
|
|
449
|
+
return @parsed_package_contents if defined?(@parsed_package_contents)
|
|
450
|
+
|
|
451
|
+
begin
|
|
452
|
+
@parsed_package_contents = JSON.parse(package_json_contents)
|
|
453
|
+
rescue JSON::ParserError => e
|
|
454
|
+
raise ReactOnRails::Error, <<~MSG.strip
|
|
455
|
+
**ERROR** ReactOnRails: Failed to parse package.json file.
|
|
456
|
+
|
|
457
|
+
Location: #{package_json}
|
|
458
|
+
Error: #{e.message}
|
|
459
|
+
|
|
460
|
+
The package.json file contains invalid JSON. Please check the file for syntax errors.
|
|
461
|
+
|
|
462
|
+
Common issues:
|
|
463
|
+
- Missing or extra commas
|
|
464
|
+
- Unquoted keys or values
|
|
465
|
+
- Trailing commas (not allowed in JSON)
|
|
466
|
+
- Comments (not allowed in standard JSON)
|
|
467
|
+
MSG
|
|
468
|
+
end
|
|
469
|
+
end
|
|
123
470
|
end
|
|
471
|
+
# rubocop:enable Metrics/ClassLength
|
|
124
472
|
end
|
|
125
473
|
end
|
|
@@ -17,18 +17,24 @@ namespace :react_on_rails do
|
|
|
17
17
|
DESC
|
|
18
18
|
|
|
19
19
|
task generate_packs: :environment do
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
verbose = ENV["REACT_ON_RAILS_VERBOSE"] == "true"
|
|
21
|
+
|
|
22
|
+
if verbose
|
|
23
|
+
puts Rainbow("🚀 Starting React on Rails pack generation...").bold
|
|
24
|
+
puts Rainbow("📁 Auto-load bundle: #{ReactOnRails.configuration.auto_load_bundle}").cyan
|
|
25
|
+
puts Rainbow("📂 Components subdirectory: #{ReactOnRails.configuration.components_subdirectory}").cyan
|
|
26
|
+
puts ""
|
|
27
|
+
end
|
|
24
28
|
|
|
25
29
|
begin
|
|
26
30
|
start_time = Time.now
|
|
27
31
|
ReactOnRails::PacksGenerator.instance.generate_packs_if_stale
|
|
28
32
|
end_time = Time.now
|
|
29
33
|
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
if verbose
|
|
35
|
+
puts ""
|
|
36
|
+
puts Rainbow("✨ Pack generation completed in #{((end_time - start_time) * 1000).round(1)}ms").green
|
|
37
|
+
end
|
|
32
38
|
rescue ReactOnRails::Error => e
|
|
33
39
|
handle_react_on_rails_error(e)
|
|
34
40
|
exit 1
|
data/lib/tasks/locale.rake
CHANGED
|
@@ -9,8 +9,13 @@ namespace :react_on_rails do
|
|
|
9
9
|
Generate i18n javascript files
|
|
10
10
|
This task generates javascript locale files: `translations.js` & `default.js` and places them in
|
|
11
11
|
the "ReactOnRails.configuration.i18n_dir".
|
|
12
|
+
|
|
13
|
+
Options:
|
|
14
|
+
force=true - Force regeneration even if files are up to date
|
|
15
|
+
Example: rake react_on_rails:locale force=true
|
|
12
16
|
DESC
|
|
13
17
|
task locale: :environment do
|
|
14
|
-
|
|
18
|
+
force = %w[true 1 yes].include?(ENV["force"]&.downcase)
|
|
19
|
+
ReactOnRails::Locales.compile(force: force)
|
|
15
20
|
end
|
|
16
21
|
end
|
data/rakelib/docker.rake
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :docker do
|
|
4
|
+
desc "Run Rubocop linter from docker"
|
|
5
|
+
task :rubocop do
|
|
6
|
+
sh "docker-compose run lint rake lint:rubocop"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
desc "Run stylelint linter from docker"
|
|
10
|
+
task :scss do
|
|
11
|
+
sh "docker-compose run lint rake lint:scss"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
desc "Run eslint linter from docker"
|
|
15
|
+
task :eslint do
|
|
16
|
+
sh "docker-compose run lint rake lint:eslint"
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
desc "Run all linting from docker"
|
|
20
|
+
task :lint do
|
|
21
|
+
sh "docker-compose run lint rake lint"
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
desc "Runs all linters from docker. Run `rake -D docker` to see all available lint options"
|
|
26
|
+
task docker: ["docker:lint"]
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative "task_helpers"
|
|
4
|
+
|
|
5
|
+
namespace :dummy_apps do
|
|
6
|
+
include ReactOnRails::TaskHelpers
|
|
7
|
+
|
|
8
|
+
task :pnpm_install do
|
|
9
|
+
pnpm_install_cmd = "pnpm install"
|
|
10
|
+
sh_in_dir(dummy_app_dir, pnpm_install_cmd)
|
|
11
|
+
sh_in_dir(dummy_app_dir, "yalc link react-on-rails")
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
task dummy_app: [:pnpm_install] do
|
|
15
|
+
dummy_app_dir = File.join(gem_root, "spec/dummy")
|
|
16
|
+
bundle_install_in(dummy_app_dir)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
task :generate_packs do
|
|
20
|
+
dummy_app_dir = File.join(gem_root, "spec/dummy")
|
|
21
|
+
sh_in_dir(dummy_app_dir, "bundle exec rake react_on_rails:generate_packs")
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
task dummy_apps: %i[dummy_app node_package generate_packs] do
|
|
25
|
+
puts "Prepared all Dummy Apps"
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
desc "Prepares all dummy apps by installing dependencies"
|
|
30
|
+
task dummy_apps: ["dummy_apps:dummy_apps"]
|