Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .lychee.toml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ exclude = [
# ============================================================================
'^https://blog\.shakacode\.com', # May block automated requests
'^https?://(www\.)?foxford\.ru', # Russian site, often blocks bots
'^https://(www\.)?guavapass\.com', # TLS handshake fails from GitHub Actions (bot filter)
'^https://(www\.)?airgoat\.com', # Returns 403
'^https://(www\.)?first\.io', # Returns 403
'^https://(www\.)?estately\.com', # Returns 403
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ After a release, run `/update-changelog` in Claude Code to analyze commits, writ

### [Unreleased]

#### Removed

- **[Pro]** **Removed the `--rsc-pro` install generator flag**: `--rsc` already implies Pro, so the separate mode was unnecessary. Behaviors previously gated on `--rsc-pro` (Pro verification checklist, prerelease install note, exact Pro gem pin on prereleases) now fire on `--rsc` installs. See also [Issue 3104](https://github.com/shakacode/react_on_rails/issues/3104), which tracks unrelated silent-failure bugs in the Pro upgrade automation. [PR 3105](https://github.com/shakacode/react_on_rails/pull/3105) by [ihabadham](https://github.com/ihabadham).

#### Changed

- **[Pro]** **Pro generator now creates the Node Renderer at `renderer/node-renderer.js`**: The canonical location for the Node Renderer entry point is now a dedicated top-level `renderer/` directory instead of `client/`, making it straightforward to exclude from production Docker builds that strip JS sources after bundling. Docs and Pro `spec/dummy` now use the new path consistently. Existing apps are unaffected — the generator skips files that already exist (including a legacy `client/node-renderer.js`). Fixes [Issue 3073](https://github.com/shakacode/react_on_rails/issues/3073). [PR 3165](https://github.com/shakacode/react_on_rails/pull/3165) by [justin808](https://github.com/justin808).
Expand Down
18 changes: 5 additions & 13 deletions react_on_rails/lib/generators/react_on_rails/generator_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -152,28 +152,20 @@ def mark_pro_gem_installed!
@pro_gem_installed = true
end

# Check if first-class RSC Pro mode should be enabled.
# Returns true when --rsc-pro is set, or when users explicitly pass both --rsc and --pro.
#
# @return [Boolean] true if RSC Pro mode semantics should be applied
def use_rsc_pro_mode?
options[:rsc_pro] || (options[:rsc] && options[:pro])
end

# Check if Pro features should be enabled.
# Returns true if --pro, --rsc, or --rsc-pro is set (RSC implies Pro).
# Returns true if --pro or --rsc is set (RSC implies Pro).
#
# @return [Boolean] true if Pro setup should be included
def use_pro?
options[:pro] || options[:rsc] || options[:rsc_pro]
options[:pro] || options[:rsc]
end

# Check if RSC (React Server Components) should be enabled
# Returns true if --rsc or --rsc-pro is explicitly set
# Check if RSC (React Server Components) should be enabled.
# Returns true if --rsc is set.
#
# @return [Boolean] true if RSC setup should be included
def use_rsc?
options[:rsc] || options[:rsc_pro]
options[:rsc]
end

# Determine if the project is using rspack as the bundler.
Expand Down
20 changes: 5 additions & 15 deletions react_on_rails/lib/generators/react_on_rails/install_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,21 +57,13 @@ class InstallGenerator < Rails::Generators::Base
class_option :pro,
type: :boolean,
default: false,
desc: "Install React on Rails Pro with Node Renderer. " \
"Combined with --rsc, uses --rsc-pro mode. Default: false"
desc: "Install React on Rails Pro with Node Renderer. Default: false"

# --rsc
class_option :rsc,
type: :boolean,
default: false,
desc: "Install React Server Components support (includes Pro). " \
"Combined with --pro, uses --rsc-pro mode. Default: false"

# --rsc-pro
class_option :rsc_pro,
type: :boolean,
default: false,
desc: "Install first-class Pro RSC mode with matched Pro/RSC defaults. Default: false"
desc: "Install React Server Components support (includes Pro). Default: false"

# Hidden option: allows tests (and advanced users) to signal that Shakapacker
# was just installed, triggering force-overwrite of shakapacker.yml with RoR's template.
Expand Down Expand Up @@ -644,7 +636,7 @@ def add_post_install_message
ci_workflow_generated: @ci_workflow_generated == true,
app_root: destination_root
))
GeneratorMessages.add_info(rsc_pro_verification_message) if use_rsc_pro_mode?
GeneratorMessages.add_info(rsc_verification_message) if use_rsc?
end

def shakapacker_setup_incomplete?
Expand All @@ -658,9 +650,7 @@ def recovery_install_command
flags << "--typescript" if options.typescript?
flags << "--rspack" if options.rspack?

if use_rsc_pro_mode?
flags << "--rsc-pro"
elsif options.rsc?
if options.rsc?
flags << "--rsc"
elsif options.pro?
flags << "--pro"
Expand All @@ -669,7 +659,7 @@ def recovery_install_command
["rails generate react_on_rails:install", *flags].join(" ")
end

def rsc_pro_verification_message
def rsc_verification_message
<<~MSG

🔎 RSC Pro Verification:
Expand Down
27 changes: 14 additions & 13 deletions react_on_rails/lib/generators/react_on_rails/pro_setup.rb
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,12 @@ def missing_pro_gem?(force: false)
return false if pro_gem_installed?
return false if attempt_pro_gem_auto_install

context_line = pro_gem_requirement_context_line
prerelease_note = rsc_pro_prerelease_note
optional_prerelease_line = prerelease_note.empty? ? "" : "\n#{prerelease_note}"

GeneratorMessages.add_error(<<~MSG.strip)
🚫 Failed to auto-install #{PRO_GEM_NAME} gem.

#{context_line}
#{prerelease_note}
#{pro_gem_requirement_context_line}#{optional_prerelease_line}

Please add manually to your Gemfile:
gem '#{PRO_GEM_NAME}', '#{pro_gem_version_requirement}'
Expand All @@ -94,20 +92,16 @@ def pro_flag_specified_for_context?
end

def pro_requirement_flag
return "--rsc-pro" if use_rsc_pro_mode?
return "--rsc" if options[:rsc]

"--pro"
end

def rsc_pro_prerelease_note
return "" unless use_rsc_pro_mode?
return "" unless Gem::Version.new(ReactOnRails::VERSION).prerelease?
def prerelease_note
return "" unless prerelease_ror_version?

"Note: #{PRO_GEM_NAME} #{ReactOnRails::VERSION} may not be published yet. " \
"If you are testing from source, use a local Gemfile `path:` option."
rescue ArgumentError
""
end

# Attempt to auto-install the Pro gem via bundle add.
Expand Down Expand Up @@ -537,13 +531,20 @@ def pro_gem_auto_install_command
end

def pro_gem_version_requirement
# RSC Pro uses exact pinning so the Pro gem version always matches the
# paired RSC package version generated in the same run.
return ReactOnRails::VERSION if use_rsc_pro_mode?
# Prerelease gem versions need an exact pin: Bundler's pessimistic operator
# (~>) does not match prerelease versions, so a stable range would fail to
# install during prerelease cycles.
return ReactOnRails::VERSION if prerelease_ror_version?
Comment thread
ihabadham marked this conversation as resolved.

"~> #{recommended_pro_gem_version}"
end

def prerelease_ror_version?
Gem::Version.new(ReactOnRails::VERSION).prerelease?
rescue ArgumentError
false
end

# Keep manual fallback pinned to the latest stable release (drop pre-release suffixes like .rc.N).
# react_on_rails_pro follows the same version number as react_on_rails by policy.
# Both gems are released in lockstep; if this ever changes, replace with a dedicated constant.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,29 +203,26 @@ def self.read
end
end

describe "RSC Pro mode helpers" do
it "enables rsc-pro mode for explicit --rsc-pro flag" do
allow(self).to receive(:options).and_return({ rsc_pro: true, rsc: false, pro: false })
describe "Pro/RSC flag helpers" do
it "treats --rsc as implying Pro" do
allow(self).to receive(:options).and_return({ rsc: true, pro: false })

expect(use_rsc_pro_mode?).to be(true)
expect(use_rsc?).to be(true)
expect(use_pro?).to be(true)
end

it "enables rsc-pro mode when --rsc and --pro are both set" do
allow(self).to receive(:options).and_return({ rsc_pro: false, rsc: true, pro: true })
it "enables Pro without RSC for --pro alone" do
allow(self).to receive(:options).and_return({ rsc: false, pro: true })

expect(use_rsc_pro_mode?).to be(true)
expect(use_rsc?).to be(true)
expect(use_rsc?).to be(false)
expect(use_pro?).to be(true)
end

it "does not enable rsc-pro mode for standalone --pro" do
allow(self).to receive(:options).and_return({ rsc_pro: false, rsc: false, pro: true })
it "does not enable Pro or RSC for a plain install" do
allow(self).to receive(:options).and_return({ rsc: false, pro: false })

expect(use_rsc_pro_mode?).to be(false)
expect(use_rsc?).to be(false)
expect(use_pro?).to be(true)
expect(use_pro?).to be(false)
end
end

Expand Down
Loading
Loading