react_on_rails 16.2.0.beta.3 → 16.2.0.beta.4
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 +18 -0
- data/CLAUDE.md +59 -0
- data/CONTRIBUTING.md +48 -0
- data/Gemfile.development_dependencies +1 -0
- data/Gemfile.lock +25 -2
- data/SWITCHING_CI_CONFIGS.md +55 -6
- data/Steepfile +51 -0
- data/bin/ci-rerun-failures +34 -11
- data/bin/ci-run-failed-specs +25 -1
- data/bin/ci-switch-config +254 -32
- data/bin/lefthook/check-trailing-newlines +2 -12
- data/bin/lefthook/eslint-lint +0 -10
- data/bin/lefthook/prettier-format +0 -10
- data/bin/lefthook/ruby-autofix +1 -5
- data/lib/react_on_rails/configuration.rb +56 -12
- data/lib/react_on_rails/controller.rb +3 -3
- data/lib/react_on_rails/doctor.rb +4 -2
- data/lib/react_on_rails/helper.rb +3 -3
- data/lib/react_on_rails/pro_helper.rb +2 -44
- data/lib/react_on_rails/react_component/render_options.rb +7 -7
- data/lib/react_on_rails/utils.rb +40 -0
- data/lib/react_on_rails/version.rb +1 -1
- data/react_on_rails_pro/CHANGELOG.md +135 -29
- data/react_on_rails_pro/Gemfile.development_dependencies +1 -0
- data/react_on_rails_pro/Gemfile.lock +6 -3
- data/react_on_rails_pro/README.md +559 -38
- data/react_on_rails_pro/docs/installation.md +40 -22
- data/react_on_rails_pro/docs/node-renderer/basics.md +26 -19
- data/react_on_rails_pro/docs/node-renderer/js-configuration.md +24 -22
- data/react_on_rails_pro/docs/node-renderer/troubleshooting.md +2 -0
- data/react_on_rails_pro/lib/react_on_rails_pro/version.rb +1 -1
- data/react_on_rails_pro/package.json +1 -1
- data/react_on_rails_pro/packages/node-renderer/src/master/restartWorkers.ts +39 -17
- data/react_on_rails_pro/packages/node-renderer/src/master.ts +15 -4
- data/react_on_rails_pro/packages/node-renderer/src/shared/configBuilder.ts +44 -5
- data/react_on_rails_pro/packages/node-renderer/src/shared/utils.ts +4 -2
- data/react_on_rails_pro/packages/node-renderer/src/worker/handleGracefulShutdown.ts +49 -0
- data/react_on_rails_pro/packages/node-renderer/src/worker/vm.ts +3 -3
- data/react_on_rails_pro/packages/node-renderer/src/worker.ts +5 -2
- data/react_on_rails_pro/packages/node-renderer/tests/helper.ts +8 -8
- data/react_on_rails_pro/packages/node-renderer/tests/testingNodeRendererConfigs.js +1 -1
- data/react_on_rails_pro/packages/node-renderer/tests/worker.test.ts +19 -19
- data/react_on_rails_pro/rakelib/rbs.rake +47 -0
- data/react_on_rails_pro/sig/react_on_rails_pro/cache.rbs +13 -0
- data/react_on_rails_pro/sig/react_on_rails_pro/configuration.rbs +100 -0
- data/react_on_rails_pro/sig/react_on_rails_pro/error.rbs +4 -0
- data/react_on_rails_pro/sig/react_on_rails_pro/utils.rbs +7 -0
- data/react_on_rails_pro/sig/react_on_rails_pro.rbs +5 -0
- data/react_on_rails_pro/spec/dummy/Gemfile.lock +6 -3
- data/react_on_rails_pro/spec/dummy/client/node-renderer.js +1 -1
- data/react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb +16 -17
- data/sig/react_on_rails/controller.rbs +1 -1
- data/sig/react_on_rails/error.rbs +4 -0
- data/sig/react_on_rails/helper.rbs +2 -2
- data/sig/react_on_rails/json_parse_error.rbs +10 -0
- data/sig/react_on_rails/prerender_error.rbs +21 -0
- data/sig/react_on_rails/smart_error.rbs +28 -0
- data/sig/react_on_rails.rbs +3 -24
- metadata +14 -3
- data/lib/react_on_rails/pro_utils.rb +0 -37
|
@@ -11,7 +11,7 @@ def change_text_expect_dom_selector(dom_selector, expect_no_change: false)
|
|
|
11
11
|
find("input").set new_text
|
|
12
12
|
within("h3") do
|
|
13
13
|
if expect_no_change
|
|
14
|
-
expect(subject).
|
|
14
|
+
expect(subject).not_to have_content new_text
|
|
15
15
|
else
|
|
16
16
|
expect(subject).to have_content new_text
|
|
17
17
|
end
|
|
@@ -110,7 +110,7 @@ describe "Turbolinks across pages", :js do
|
|
|
110
110
|
it "changes name in message according to input" do
|
|
111
111
|
visit "/client_side_hello_world"
|
|
112
112
|
change_text_expect_dom_selector("#HelloWorld-react-component-0")
|
|
113
|
-
click_link "Hello World Component Server Rendered, with extra options"
|
|
113
|
+
click_link "Hello World Component Server Rendered, with extra options"
|
|
114
114
|
change_text_expect_dom_selector("#my-hello-world-id")
|
|
115
115
|
end
|
|
116
116
|
end
|
|
@@ -174,19 +174,19 @@ describe "React Router", :js do
|
|
|
174
174
|
|
|
175
175
|
before do
|
|
176
176
|
visit "/"
|
|
177
|
-
click_link "React Router"
|
|
177
|
+
click_link "React Router"
|
|
178
178
|
end
|
|
179
179
|
|
|
180
180
|
context "when rendering /react_router" do
|
|
181
181
|
it { is_expected.to have_text("Woohoo, we can use react-router here!") }
|
|
182
182
|
|
|
183
183
|
it "clicking links correctly renders other pages" do
|
|
184
|
-
click_link "Router First Page"
|
|
184
|
+
click_link "Router First Page"
|
|
185
185
|
expect(page).to have_current_path("/react_router/first_page")
|
|
186
186
|
first_page_header_text = page.find(:css, "h2#first-page").text
|
|
187
187
|
expect(first_page_header_text).to eq("React Router First Page")
|
|
188
188
|
|
|
189
|
-
click_link "Router Second Page"
|
|
189
|
+
click_link "Router Second Page"
|
|
190
190
|
expect(page).to have_current_path("/react_router/second_page")
|
|
191
191
|
second_page_header_text = page.find(:css, "h2#second-page").text
|
|
192
192
|
expect(second_page_header_text).to eq("React Router Second Page")
|
|
@@ -239,12 +239,12 @@ describe "async render function returns component", :js do
|
|
|
239
239
|
end
|
|
240
240
|
end
|
|
241
241
|
|
|
242
|
-
describe "Manual client hydration", :js do
|
|
242
|
+
describe "Manual client hydration", :js, type: :system do
|
|
243
243
|
before { visit "/xhr_refresh" }
|
|
244
244
|
|
|
245
245
|
it "HelloWorldRehydratable onChange should trigger" do
|
|
246
246
|
within("form") do
|
|
247
|
-
click_button "refresh"
|
|
247
|
+
click_button "refresh"
|
|
248
248
|
end
|
|
249
249
|
within("#HelloWorldRehydratable-react-component-1") do
|
|
250
250
|
find("input").set "Should update"
|
|
@@ -396,20 +396,20 @@ shared_examples "streamed component tests" do |path, selector|
|
|
|
396
396
|
|
|
397
397
|
it "hydrates the component" do
|
|
398
398
|
visit path
|
|
399
|
-
expect(page.html).to
|
|
399
|
+
expect(page.html).to match(/client-bundle[^\"]*.js/)
|
|
400
400
|
change_text_expect_dom_selector(selector)
|
|
401
401
|
end
|
|
402
402
|
|
|
403
403
|
it "renders the page completely on server and displays content on client even without JavaScript" do
|
|
404
404
|
# Don't add client-bundle.js to the page to ensure that the app is not hydrated
|
|
405
405
|
visit "#{path}?skip_js_packs=true"
|
|
406
|
-
expect(page.html).not_to
|
|
406
|
+
expect(page.html).not_to match(/client-bundle[^\"]*.js/)
|
|
407
407
|
# Ensure that the component state is not updated
|
|
408
408
|
change_text_expect_dom_selector(selector, expect_no_change: true)
|
|
409
409
|
|
|
410
|
-
expect(page).
|
|
411
|
-
expect(page).
|
|
412
|
-
expect(page).
|
|
410
|
+
expect(page).not_to have_text "Loading branch1"
|
|
411
|
+
expect(page).not_to have_text "Loading branch2"
|
|
412
|
+
expect(page).not_to have_text(/Loading branch1 at level \d+/)
|
|
413
413
|
expect(page).to have_text(/branch1 \(level \d+\)/, count: 5)
|
|
414
414
|
end
|
|
415
415
|
|
|
@@ -417,18 +417,17 @@ shared_examples "streamed component tests" do |path, selector|
|
|
|
417
417
|
# visit waits for the page to load, so we ensure that the page is loaded before checking the hydration status
|
|
418
418
|
visit "#{path}?skip_js_packs=true"
|
|
419
419
|
expect(page).to have_text "HydrationStatus: Streaming server render"
|
|
420
|
-
expect(page).
|
|
421
|
-
expect(page).
|
|
420
|
+
expect(page).not_to have_text "HydrationStatus: Hydrated"
|
|
421
|
+
expect(page).not_to have_text "HydrationStatus: Page loaded"
|
|
422
422
|
end
|
|
423
423
|
end
|
|
424
424
|
|
|
425
|
-
describe "Pages/stream_async_components_for_testing", :js
|
|
426
|
-
skip: "Flaky test replaced by Playwright E2E tests in e2e-tests/streaming.spec.ts" do
|
|
425
|
+
describe "Pages/stream_async_components_for_testing", :js do
|
|
427
426
|
it_behaves_like "streamed component tests", "/stream_async_components_for_testing",
|
|
428
427
|
"#AsyncComponentsTreeForTesting-react-component-0"
|
|
429
428
|
end
|
|
430
429
|
|
|
431
|
-
describe "React Router Sixth Page", :js
|
|
430
|
+
describe "React Router Sixth Page", :js do
|
|
432
431
|
it_behaves_like "streamed component tests", "/server_router/streaming-server-component",
|
|
433
432
|
"#ServerComponentRouter-react-component-0"
|
|
434
433
|
end
|
|
@@ -21,7 +21,7 @@ module ReactOnRails
|
|
|
21
21
|
# Returns html_safe string (ActiveSupport::SafeBuffer)
|
|
22
22
|
def redux_store: (
|
|
23
23
|
String store_name,
|
|
24
|
-
?Hash[Symbol, untyped] props
|
|
24
|
+
?Hash[Symbol, untyped] | String props
|
|
25
25
|
) -> safe_buffer
|
|
26
26
|
|
|
27
27
|
# Returns html_safe string (ActiveSupport::SafeBuffer)
|
|
@@ -33,7 +33,7 @@ module ReactOnRails
|
|
|
33
33
|
?Hash[Symbol, untyped] options
|
|
34
34
|
) -> safe_buffer
|
|
35
35
|
|
|
36
|
-
def sanitized_props_string: (untyped props) -> String
|
|
36
|
+
def sanitized_props_string: (Hash[Symbol, untyped] | String props) -> String
|
|
37
37
|
|
|
38
38
|
def rails_context: (
|
|
39
39
|
?server_side: bool
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
module ReactOnRails
|
|
2
|
+
class JsonParseError < ::ReactOnRails::Error
|
|
3
|
+
attr_reader json: String
|
|
4
|
+
|
|
5
|
+
def initialize: (parse_error: StandardError, json: String) -> void
|
|
6
|
+
def to_honeybadger_context: () -> Hash[Symbol, untyped]
|
|
7
|
+
def raven_context: () -> Hash[Symbol, untyped]
|
|
8
|
+
def to_error_context: () -> Hash[Symbol, untyped]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
module ReactOnRails
|
|
2
|
+
class PrerenderError < ::ReactOnRails::Error
|
|
3
|
+
MAX_ERROR_SNIPPET_TO_LOG: Integer
|
|
4
|
+
|
|
5
|
+
attr_reader component_name: String?
|
|
6
|
+
attr_reader err: StandardError?
|
|
7
|
+
attr_reader props: String?
|
|
8
|
+
attr_reader js_code: String?
|
|
9
|
+
attr_reader console_messages: String?
|
|
10
|
+
|
|
11
|
+
def initialize: (?component_name: String?, ?err: StandardError?, ?props: String?, ?js_code: String?, ?console_messages: String?) -> void
|
|
12
|
+
def to_honeybadger_context: () -> Hash[Symbol, untyped]
|
|
13
|
+
def raven_context: () -> Hash[Symbol, untyped]
|
|
14
|
+
def to_error_context: () -> Hash[Symbol, untyped]
|
|
15
|
+
|
|
16
|
+
private
|
|
17
|
+
|
|
18
|
+
def calc_message: (String? component_name, String? console_messages, StandardError? err, String? js_code, String? props) -> [String?, String]
|
|
19
|
+
def build_troubleshooting_suggestions: (String? component_name, StandardError? err, String? console_messages) -> String
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module ReactOnRails
|
|
2
|
+
class SmartError < Error
|
|
3
|
+
attr_reader error_type: Symbol
|
|
4
|
+
attr_reader component_name: String?
|
|
5
|
+
attr_reader props: String?
|
|
6
|
+
attr_reader js_code: String?
|
|
7
|
+
attr_reader additional_context: Hash[Symbol, untyped]
|
|
8
|
+
|
|
9
|
+
def initialize: (error_type: Symbol, ?component_name: String?, ?props: String?, ?js_code: String?, **untyped additional_context) -> void
|
|
10
|
+
def solution: () -> String
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def build_error_message: () -> String
|
|
15
|
+
def error_type_title: () -> String
|
|
16
|
+
def error_description: () -> String
|
|
17
|
+
def component_not_registered_solution: () -> String
|
|
18
|
+
def missing_auto_loaded_bundle_solution: () -> String
|
|
19
|
+
def hydration_mismatch_solution: () -> String
|
|
20
|
+
def server_rendering_error_solution: () -> String
|
|
21
|
+
def redux_store_not_found_solution: () -> String
|
|
22
|
+
def configuration_error_solution: () -> String
|
|
23
|
+
def default_solution: () -> String
|
|
24
|
+
def additional_info: () -> String
|
|
25
|
+
def troubleshooting_section: () -> String
|
|
26
|
+
def find_similar_components: (String name) -> Array[String]
|
|
27
|
+
end
|
|
28
|
+
end
|
data/sig/react_on_rails.rbs
CHANGED
|
@@ -9,30 +9,9 @@ module ReactOnRails
|
|
|
9
9
|
def self.configure: () { (Configuration) -> void } -> void
|
|
10
10
|
def self.configuration: () -> Configuration
|
|
11
11
|
|
|
12
|
+
# Error classes are defined in separate RBS files:
|
|
13
|
+
# - sig/react_on_rails/prerender_error.rbs
|
|
14
|
+
# - sig/react_on_rails/json_parse_error.rbs
|
|
12
15
|
class Error < StandardError
|
|
13
16
|
end
|
|
14
|
-
|
|
15
|
-
class PrerenderError < Error
|
|
16
|
-
attr_reader component_name: String?
|
|
17
|
-
attr_reader js_code: String?
|
|
18
|
-
attr_reader err: Hash[Symbol, untyped]?
|
|
19
|
-
attr_reader props: (Hash[Symbol, untyped] | String)?
|
|
20
|
-
attr_reader console_messages: Array[String]?
|
|
21
|
-
|
|
22
|
-
def initialize: (
|
|
23
|
-
?component_name: String?,
|
|
24
|
-
?js_code: String?,
|
|
25
|
-
?err: Hash[Symbol, untyped]?,
|
|
26
|
-
?props: (Hash[Symbol, untyped] | String)?,
|
|
27
|
-
?console_messages: Array[String]?
|
|
28
|
-
) -> void
|
|
29
|
-
|
|
30
|
-
def to_honeybadger_context: () -> Hash[Symbol, untyped]
|
|
31
|
-
def raven_context: () -> Hash[Symbol, untyped]
|
|
32
|
-
def to_error_context: () -> Hash[Symbol, untyped]
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
class JsonParseError < Error
|
|
36
|
-
def initialize: (Hash[Symbol, untyped] err) -> void
|
|
37
|
-
end
|
|
38
17
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: react_on_rails
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 16.2.0.beta.
|
|
4
|
+
version: 16.2.0.beta.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Justin Gordon
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2025-11-
|
|
11
|
+
date: 2025-11-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: addressable
|
|
@@ -137,6 +137,7 @@ files:
|
|
|
137
137
|
- Rakefile
|
|
138
138
|
- SUMMARY.md
|
|
139
139
|
- SWITCHING_CI_CONFIGS.md
|
|
140
|
+
- Steepfile
|
|
140
141
|
- TODO.md
|
|
141
142
|
- WARP.md
|
|
142
143
|
- app/helpers/react_on_rails_helper.rb
|
|
@@ -243,7 +244,6 @@ files:
|
|
|
243
244
|
- lib/react_on_rails/packs_generator.rb
|
|
244
245
|
- lib/react_on_rails/prerender_error.rb
|
|
245
246
|
- lib/react_on_rails/pro_helper.rb
|
|
246
|
-
- lib/react_on_rails/pro_utils.rb
|
|
247
247
|
- lib/react_on_rails/react_component/render_options.rb
|
|
248
248
|
- lib/react_on_rails/server_rendering_js_code.rb
|
|
249
249
|
- lib/react_on_rails/server_rendering_pool.rb
|
|
@@ -378,6 +378,7 @@ files:
|
|
|
378
378
|
- react_on_rails_pro/packages/node-renderer/src/worker.ts
|
|
379
379
|
- react_on_rails_pro/packages/node-renderer/src/worker/authHandler.ts
|
|
380
380
|
- react_on_rails_pro/packages/node-renderer/src/worker/checkProtocolVersionHandler.ts
|
|
381
|
+
- react_on_rails_pro/packages/node-renderer/src/worker/handleGracefulShutdown.ts
|
|
381
382
|
- react_on_rails_pro/packages/node-renderer/src/worker/handleRenderRequest.ts
|
|
382
383
|
- react_on_rails_pro/packages/node-renderer/src/worker/types.ts
|
|
383
384
|
- react_on_rails_pro/packages/node-renderer/src/worker/vm.ts
|
|
@@ -430,6 +431,7 @@ files:
|
|
|
430
431
|
- react_on_rails_pro/rakelib/dummy_apps.rake
|
|
431
432
|
- react_on_rails_pro/rakelib/lint.rake
|
|
432
433
|
- react_on_rails_pro/rakelib/public_key_management.rake
|
|
434
|
+
- react_on_rails_pro/rakelib/rbs.rake
|
|
433
435
|
- react_on_rails_pro/rakelib/run_rspec.rake
|
|
434
436
|
- react_on_rails_pro/rakelib/task_helpers.rb
|
|
435
437
|
- react_on_rails_pro/rakelib/yard.rake
|
|
@@ -439,6 +441,11 @@ files:
|
|
|
439
441
|
- react_on_rails_pro/script/preinstall.js
|
|
440
442
|
- react_on_rails_pro/script/setup
|
|
441
443
|
- react_on_rails_pro/script/test
|
|
444
|
+
- react_on_rails_pro/sig/react_on_rails_pro.rbs
|
|
445
|
+
- react_on_rails_pro/sig/react_on_rails_pro/cache.rbs
|
|
446
|
+
- react_on_rails_pro/sig/react_on_rails_pro/configuration.rbs
|
|
447
|
+
- react_on_rails_pro/sig/react_on_rails_pro/error.rbs
|
|
448
|
+
- react_on_rails_pro/sig/react_on_rails_pro/utils.rbs
|
|
442
449
|
- react_on_rails_pro/spec/.rubocop.yml
|
|
443
450
|
- react_on_rails_pro/spec/dummy/.browserslistrc
|
|
444
451
|
- react_on_rails_pro/spec/dummy/.gitignore
|
|
@@ -966,10 +973,14 @@ files:
|
|
|
966
973
|
- sig/react_on_rails.rbs
|
|
967
974
|
- sig/react_on_rails/configuration.rbs
|
|
968
975
|
- sig/react_on_rails/controller.rbs
|
|
976
|
+
- sig/react_on_rails/error.rbs
|
|
969
977
|
- sig/react_on_rails/git_utils.rbs
|
|
970
978
|
- sig/react_on_rails/helper.rbs
|
|
979
|
+
- sig/react_on_rails/json_parse_error.rbs
|
|
971
980
|
- sig/react_on_rails/packer_utils.rbs
|
|
981
|
+
- sig/react_on_rails/prerender_error.rbs
|
|
972
982
|
- sig/react_on_rails/server_rendering_pool.rbs
|
|
983
|
+
- sig/react_on_rails/smart_error.rbs
|
|
973
984
|
- sig/react_on_rails/test_helper.rbs
|
|
974
985
|
- sig/react_on_rails/utils.rbs
|
|
975
986
|
- sig/react_on_rails/version_checker.rbs
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module ReactOnRails
|
|
4
|
-
module ProUtils
|
|
5
|
-
PRO_ONLY_OPTIONS = %i[immediate_hydration].freeze
|
|
6
|
-
|
|
7
|
-
# Checks if React on Rails Pro features are available
|
|
8
|
-
# @return [Boolean] true if Pro is installed and licensed, false otherwise
|
|
9
|
-
def self.support_pro_features?
|
|
10
|
-
ReactOnRails::Utils.react_on_rails_pro?
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.disable_pro_render_options_if_not_licensed(raw_options)
|
|
14
|
-
if support_pro_features?
|
|
15
|
-
return {
|
|
16
|
-
raw_options: raw_options,
|
|
17
|
-
explicitly_disabled_pro_options: []
|
|
18
|
-
}
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
raw_options_after_disable = raw_options.dup
|
|
22
|
-
|
|
23
|
-
explicitly_disabled_pro_options = PRO_ONLY_OPTIONS.select do |option|
|
|
24
|
-
# Use global configuration if it's not overridden in the options
|
|
25
|
-
next ReactOnRails.configuration.send(option) if raw_options[option].nil?
|
|
26
|
-
|
|
27
|
-
raw_options[option]
|
|
28
|
-
end
|
|
29
|
-
explicitly_disabled_pro_options.each { |option| raw_options_after_disable[option] = false }
|
|
30
|
-
|
|
31
|
-
{
|
|
32
|
-
raw_options: raw_options_after_disable,
|
|
33
|
-
explicitly_disabled_pro_options: explicitly_disabled_pro_options
|
|
34
|
-
}
|
|
35
|
-
end
|
|
36
|
-
end
|
|
37
|
-
end
|