Skip to content

Conversation

@AbanoubGhadban
Copy link
Collaborator

@AbanoubGhadban AbanoubGhadban commented Oct 23, 2025

Summary

This PR migrates Pro-specific configurations and utilities from the open-source React on Rails gem to the React on Rails Pro gem, improving code separation and clarifying feature boundaries.

Closes #1874

Implementation Progress

Phase Checklist

  • Phase 1: Update Documentation & CHANGELOG

    • Updated CHANGELOG.md with breaking changes
    • Updated react_on_rails_pro/CHANGELOG.md to document additions
    • Moved RSC configuration docs to Pro gem
    • Added Pro-only view helpers section
    • Added Pro feature notices to streaming docs
  • Phase 2: Move RSC Configuration Options to Pro Gem

    • Removed RSC configs from ReactOnRails::Configuration
    • Added RSC configs to ReactOnRailsPro::Configuration
    • Updated all code references to use Pro config
    • Updated Pro dummy app configuration
    • Updated tests
  • Phase 3: Move RSC Utility Methods to Pro Gem

    • Move rsc_support_enabled? to Pro
    • Move rsc_bundle_js_file_path to Pro
    • Move react_server_client_manifest_file_path to Pro
  • Phase 4: Move Streaming Helper Methods to Pro Gem

    • Move stream_react_component to Pro
    • Move rsc_payload_react_component to Pro
  • Phase 5: Move Internal Streaming Methods to Pro Gem

    • Move internal_stream_react_component to Pro
    • Move internal_rsc_payload_react_component to Pro
    • Move run_stream_inside_fiber to Pro
    • Move streaming support methods to Pro
  • Phase 6: Move Streaming Render Modes & Options to Pro Gem

    • Move :html_streaming render mode to Pro
    • Move :rsc_payload_streaming render mode to Pro
    • Move streaming render options to Pro
  • Phase 7: Move RSC Pack Generation Logic to Pro Gem

    • Move client_entrypoint? to Pro
    • Move RSC pack generation logic to Pro
  • Phase 8: Update Doctor Diagnostics

    • Update RSC detection to check for Pro
    • Update messaging for Pro requirements
  • Phase 9: Update Generator Templates

    • Remove Pro-only config examples from templates
    • Add Pro documentation references
  • Phase 10: Update Both Dummy Apps

    • Verify spec/dummy works without Pro
    • Verify react_on_rails_pro/spec/dummy works with Pro
  • Phase 11: Final Cleanup & Verification

    • Search for remaining references
    • Update comments
    • Verify error messages
    • Final testing

What Stays in Open-Source

  • immediate_hydration config (with Pro marketing badge)
  • server_bundle_output_path (used by core SSR)
  • enforce_private_server_bundles (security for all)
  • component_registry_timeout (used by core)
  • ProHelper module (for Pro marketing badges)
  • ProUtils module (for feature detection)
  • Pro detection utilities
  • Core helpers and standard render modes

What Moves to Pro

  • RSC bundle and manifest configurations
  • Streaming view helpers (stream_react_component, rsc_payload_react_component)
  • Streaming render modes (:html_streaming, :rsc_payload_streaming)
  • RSC utility methods
  • RSC pack generation logic

Breaking Changes

For Pro Users

Pro users must update their configuration:

Before:

ReactOnRails.configure do |config|
  config.rsc_bundle_js_file = "rsc-bundle.js"
  config.react_server_client_manifest_file = "react-server-client-manifest.json"
  config.react_client_manifest_file = "react-client-manifest.json"
end

After:

ReactOnRailsPro.configure do |config|
  config.rsc_bundle_js_file = "rsc-bundle.js"
  config.react_server_client_manifest_file = "react-server-client-manifest.json"
  config.react_client_manifest_file = "react-client-manifest.json"
end

For Open-Source Users

No breaking changes - open-source users never used these Pro-only features.

Benefits

  • Clearer separation - Pro features clearly distinguished
  • Smaller open-source gem - Removed Pro-specific code
  • Better documentation - Pro docs live in Pro gem
  • Clear migration path - Well-documented in CHANGELOG
  • No code duplication - Single source of truth for each feature

This change is Reviewable

Summary by CodeRabbit

  • Breaking Changes

    • React Server Components (RSC) and streaming view helpers are now Pro-only; RSC-related configuration must be moved to the Pro package.
  • Documentation

    • API docs and changelog updated with Pro-only guidance and migration steps for RSC features.
  • Chores

    • Added an ignore pattern to repository config.
  • Tests

    • Test suites updated and reorganized to cover Pro-based RSC configuration and streaming helpers.

- Updated CHANGELOG.md with breaking changes for RSC configs and streaming helpers
- Updated react_on_rails_pro/CHANGELOG.md to document additions to Pro gem
- Moved RSC configuration documentation to Pro gem docs
- Added Pro-only view helpers section consolidating all Pro helpers
- Added prominent Pro feature notices to streaming documentation
- Removed inaccurate claims about error behavior

Related to #1874
Moved RSC-specific configurations from open-source to Pro gem:
- rsc_bundle_js_file
- react_client_manifest_file
- react_server_client_manifest_file

Changes:
- Removed RSC configs from ReactOnRails::Configuration
- Added RSC configs to ReactOnRailsPro::Configuration with same defaults
- Updated all code references to use Pro config when available
- Updated Pro dummy app to use ReactOnRailsPro.configure for RSC config
- Removed RSC config tests from open-source spec
- Added comprehensive RSC config tests to Pro spec

Files modified:
- lib/react_on_rails/configuration.rb
- lib/react_on_rails/utils.rb
- lib/react_on_rails/test_helper/webpack_assets_status_checker.rb
- lib/react_on_rails/packer_utils.rb
- react_on_rails_pro/lib/react_on_rails_pro/configuration.rb
- react_on_rails_pro/spec/dummy/config/initializers/*.rb
- spec/react_on_rails/configuration_spec.rb
- react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb

Related to #1874
@claude
Copy link

claude bot commented Oct 23, 2025

Code Review: Move Pro-specific utilities and configurations to Pro gem

Summary

This PR successfully migrates RSC-specific configurations from the open-source gem to the Pro gem. The approach is well-structured with clear documentation and migration paths. However, there are several critical bugs that must be fixed before merging.


🚨 Critical Issues

1. Broken References in configuration.rb (lines 319-321)

Bug: The ensure_webpack_generated_files_exists method references removed configuration attributes:

self.webpack_generated_files = [
  "manifest.json",
  server_bundle_js_file,
  rsc_bundle_js_file,              # ❌ This attribute no longer exists!
  react_client_manifest_file,       # ❌ This attribute no longer exists!
  react_server_client_manifest_file # ❌ This attribute no longer exists!
].compact_blank

Impact: This will cause NoMethodError at runtime when webpack_generated_files is empty.

Fix: These attributes should only be included if Pro is available:

def ensure_webpack_generated_files_exists
  return unless webpack_generated_files.empty?

  files = ["manifest.json", server_bundle_js_file]
  
  if ReactOnRails::Utils.react_on_rails_pro?
    pro_config = ReactOnRailsPro.configuration
    files += [
      pro_config.rsc_bundle_js_file,
      pro_config.react_client_manifest_file,
      pro_config.react_server_client_manifest_file
    ]
  end
  
  self.webpack_generated_files = files.compact_blank
end

2. Broken Utility Methods in utils.rb (lines 156-182)

Bug: Three utility methods still reference the removed ReactOnRails.configuration attributes:

def self.rsc_bundle_js_file_path
  bundle_name = ReactOnRails.configuration.rsc_bundle_js_file  # ❌ NoMethodError
  @rsc_bundle_path = bundle_js_file_path(bundle_name)
end

def self.react_client_manifest_file_path
  file_name = ReactOnRails.configuration.react_client_manifest_file  # ❌ NoMethodError
  @react_client_manifest_path = ReactOnRails::PackerUtils.asset_uri_from_packer(file_name)
end

def self.react_server_client_manifest_file_path
  asset_name = ReactOnRails.configuration.react_server_client_manifest_file  # ❌ NoMethodError
  @react_server_manifest_path = bundle_js_file_path(asset_name)
end

Impact: These methods will crash when called, breaking RSC functionality.

Fix: Update to use Pro configuration:

def self.rsc_bundle_js_file_path
  return @rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?
  return nil unless react_on_rails_pro?

  bundle_name = ReactOnRailsPro.configuration.rsc_bundle_js_file
  @rsc_bundle_path = bundle_js_file_path(bundle_name)
end

def self.react_client_manifest_file_path
  return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?
  return nil unless react_on_rails_pro?

  file_name = ReactOnRailsPro.configuration.react_client_manifest_file
  @react_client_manifest_path = ReactOnRails::PackerUtils.asset_uri_from_packer(file_name)
end

def self.react_server_client_manifest_file_path
  return @react_server_manifest_path if @react_server_manifest_path && !Rails.env.development?
  return nil unless react_on_rails_pro?

  asset_name = ReactOnRailsPro.configuration.react_server_client_manifest_file
  if asset_name.nil?
    raise ReactOnRails::Error,
          "react_server_client_manifest_file is nil, ensure it is set in your Pro configuration"
  end

  @react_server_manifest_path = bundle_js_file_path(asset_name)
end

⚠️ High Priority Issues

3. Incomplete Test Cleanup

The PR removes tests from spec/react_on_rails/configuration_spec.rb (103 lines deleted) but doesn't verify that equivalent tests exist in the Pro gem. While new tests were added to react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb, we should ensure test coverage is maintained.

Recommendation:

  • Add a comment or check that all removed test scenarios are covered in Pro tests
  • Consider adding integration tests that verify the migration path works correctly

4. Potential Edge Case in webpack_assets_status_checker.rb

The conditional logic looks correct but could be simplified:

if ReactOnRails::Utils.react_on_rails_pro?
  pro_config = ReactOnRailsPro.configuration
  if bundle_name == pro_config.react_client_manifest_file
    ReactOnRails::Utils.react_client_manifest_file_path
  elsif bundle_name == pro_config.react_server_client_manifest_file
    ReactOnRails::Utils.react_server_client_manifest_file_path
  else
    ReactOnRails::Utils.bundle_js_file_path(bundle_name)
  end
else
  ReactOnRails::Utils.bundle_js_file_path(bundle_name)
end

Issue: If react_on_rails_pro? is true but the Pro config methods return nil, this could cause issues.

Recommendation: Add nil checks and better error handling.


💡 Code Quality Suggestions

5. Documentation: Migration Path

Good: The CHANGELOG provides clear before/after examples
Good: Pro documentation is updated with new configuration options

Suggestion: Consider adding a deprecation notice or warning when users have RSC configs in the open-source ReactOnRails.configure block. This would help catch migration issues early.

6. Defensive Programming

In both packer_utils.rb and utils.rb, the code checks for Pro availability:

if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)

Issue: The defined?(ReactOnRailsPro) check is redundant since react_on_rails_pro? already validates the gem is loaded.

Recommendation: Simplify to just if ReactOnRails::Utils.react_on_rails_pro?

7. Configuration Defaults

The Pro configuration sets good defaults:

DEFAULT_RSC_BUNDLE_JS_FILE = "rsc-bundle.js"
DEFAULT_REACT_CLIENT_MANIFEST_FILE = "react-client-manifest.json"
DEFAULT_REACT_SERVER_CLIENT_MANIFEST_FILE = "react-server-client-manifest.json"

Excellent: These match the previous defaults, ensuring backward compatibility.


🔒 Security Considerations

No security issues identified. The changes are purely refactoring/organizational and don't introduce security vulnerabilities.


🧪 Testing Recommendations

  1. Test without Pro gem installed: Ensure the open-source gem doesn't crash when Pro is not available
  2. Test with Pro gem but without RSC config: Verify defaults work correctly
  3. Test migration path: Create a test app with old-style config and verify the migration instructions work
  4. Test webpack_generated_files edge cases: Test when the array is empty vs. explicitly set

📊 Performance Considerations

No performance regressions expected. The changes are configuration-level and don't affect runtime performance.

The use of memoization in utils.rb is appropriate:

return @rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?

✅ What's Done Well

  1. Clear separation of concerns - Pro features are properly isolated
  2. Comprehensive documentation - Both CHANGELOG and Pro docs are well-written
  3. Good test coverage - New tests added for Pro configuration
  4. Backward compatibility - Default values match previous behavior
  5. Phased approach - The PR description shows thoughtful planning with a clear checklist
  6. Migration guide - Clear before/after examples in CHANGELOG

🎯 Action Items Before Merge

  • CRITICAL: Fix configuration.rb:319-321 to use Pro config conditionally
  • CRITICAL: Fix utils.rb:156-182 utility methods to use Pro config
  • HIGH: Add Pro availability checks with proper nil handling
  • MEDIUM: Simplify redundant defined?(ReactOnRailsPro) checks
  • MEDIUM: Verify test coverage completeness
  • LOW: Consider adding deprecation warnings for old config usage

Conclusion

This is a well-planned refactoring with excellent documentation, but it has critical bugs that will break runtime functionality. The bugs are straightforward to fix - they're all cases where code still references the removed configuration attributes instead of using the Pro configuration.

Once the critical issues are addressed, this will be a solid improvement to the codebase architecture.

Recommended Action: Request changes and fix the critical bugs before merging.


Review performed by Claude Code following React on Rails conventions from CLAUDE.md

- Remove RSC utility methods from ReactOnRails::Utils:
  - rsc_bundle_js_file_path
  - react_client_manifest_file_path
  - react_server_client_manifest_file_path

- Add these methods to ReactOnRailsPro::Utils with same functionality

- Update rsc_support_enabled? in open-source to delegate to Pro gem

- Update all internal Pro gem references to use ReactOnRailsPro::Utils:
  - react_on_rails_pro/lib/react_on_rails_pro/request.rb
  - react_on_rails_pro/lib/react_on_rails_pro/utils.rb

- Update webpack_assets_status_checker.rb to call ReactOnRailsPro::Utils

- Remove RSC utility tests from open-source spec (lines 452-839)
  - Removed rsc_bundle_js_file_path tests
  - Removed react_client_manifest_file_path tests
  - Removed react_server_client_manifest_file_path tests

- Update Pro gem test mocks to reference ReactOnRailsPro::Utils:
  - react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb
  - react_on_rails_pro/spec/react_on_rails_pro/request_spec.rb

Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link

claude bot commented Oct 23, 2025

Code Review - PR #1875: Move Pro-specific utilities and configurations to Pro gem

Thank you for this well-structured PR! This is a great architectural improvement that creates clear separation between open-source and Pro features.


Strengths

1. Excellent Architecture & Design

  • Clear separation of concerns between open-source and Pro gems
  • Well-documented migration path in CHANGELOG with before/after examples
  • Consistent naming conventions and code organization
  • Good use of delegation pattern (e.g., ReactOnRails::Utils.rsc_support_enabled? delegates to Pro)

2. Documentation Quality

  • Comprehensive CHANGELOG entries in both gems
  • Updated configuration docs with clear Pro feature notices
  • Well-written breaking changes section with practical examples
  • Good inline comments explaining the purpose of moved code

3. Code Quality

  • Clean refactoring with minimal code duplication
  • Proper use of memoization with Rails environment checks
  • Consistent error handling patterns

⚠️ Issues & Recommendations

🔴 Critical Issues

1. Missing Newline at End of File (REQUIRED by CLAUDE.md)

The file react_on_rails_pro/lib/react_on_rails_pro/utils.rb appears to be missing a trailing newline character based on the diff.

Action Required: Ensure ALL files end with a newline character before committing.

2. Potential Nil Reference Error in webpack_assets_status_checker.rb

Location: lib/react_on_rails/test_helper/webpack_assets_status_checker.rb:54-65

Issue: If ReactOnRailsPro is defined but not properly initialized, ReactOnRailsPro.configuration could be nil or the config attributes might not be set, leading to NoMethodError.

Recommendation: Add nil checking for pro_config before accessing its attributes.

🟡 Moderate Issues

3. Inconsistent Nil Checking Pattern

Location: lib/react_on_rails/packer_utils.rb:61-63

The code checks both react_on_rails_pro? AND defined?(ReactOnRailsPro). Make this pattern consistent across the codebase or document why both checks are necessary.

4. Cache Invalidation Concerns

Location: react_on_rails_pro/lib/react_on_rails_pro/utils.rb:22-48

The caching implementation uses module-level instance variables which are not thread-safe. Consider using Rails.cache or RequestStore for thread-safe caching, or document that these methods assume single-threaded SSR pools.

5. Missing Error Handling for Missing Pro Gem

Location: lib/react_on_rails/utils.rb:238-241

If react_on_rails_pro? returns true but ReactOnRailsPro is not properly loaded, this could raise NameError. Add rescue clause for graceful degradation.

🟢 Minor Suggestions

6. Typo in Method Name

Location: react_on_rails_pro/lib/react_on_rails_pro/utils.rb:186

mine_type_from_file_name should be mime_type_from_file_name.

7. Configuration Default Values Documentation

Explicitly mention default values in docs so users know they only need to configure if using different names.


🔒 Security Review

No Security Issues Found

  • No credential exposure
  • No injection vulnerabilities introduced
  • Proper error handling for file paths
  • No new external dependencies

🧪 Test Coverage Recommendations

Required Tests:

  1. Configuration Migration Tests - Verify old/new config behavior
  2. Fallback Behavior Tests - Test without Pro gem installed
  3. Integration Tests - Test with and without Pro
  4. Edge Cases - Nil values, missing files, thread-safety

📝 Pre-Commit Checklist (per CLAUDE.md)

  • Run bundle exec rubocop and fix ALL violations (MANDATORY)
  • Ensure ALL files end with a newline character (MANDATORY)
  • Run full test suite: rake
  • Test both dummy apps
  • Run linters: rake lint
  • Format code: rake autofix

🎯 Overall Assessment

Code Quality: ⭐⭐⭐⭐☆ (4/5)
Architecture: ⭐⭐⭐⭐⭐ (5/5)
Documentation: ⭐⭐⭐⭐⭐ (5/5)
Test Coverage: ⚠️ Pending (WIP)

Summary

Well-architected refactoring with excellent documentation. Primary concerns:

  1. Critical: Missing trailing newlines (required by project standards)
  2. Important: Potential nil reference errors
  3. Nice to have: Thread-safety considerations

Great work on this refactoring! The separation of concerns will make the codebase much more maintainable. 🚀

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 23, 2025

Walkthrough

This PR moves RSC (React Server Components) configurations, path resolvers, and streaming view helpers out of the open-source ReactOnRails gem into the react_on_rails_pro gem. OSS now delegates RSC detection/paths to Pro when present and removes streaming/RSC public APIs and related utils/tests; Pro adds the implementations, docs, and tests.

Changes

Cohort / File(s) Change Summary
Repo metadata
/.gitignore
Added .claude/.fuse_hidden* ignore pattern.
OSS: configuration removal
lib/react_on_rails/configuration.rb
Removed RSC-related defaults and public config attrs: rsc_bundle_js_file, react_client_manifest_file, react_server_client_manifest_file, and their initialization.
OSS: streaming helpers removal
lib/react_on_rails/helper.rb
Removed public streaming APIs stream_react_component and rsc_payload_react_component and internal streaming/fiber/NDJSON helper code.
OSS: utils & asset handling updates
lib/react_on_rails/utils.rb, lib/react_on_rails/packer_utils.rb, lib/react_on_rails/test_helper/webpack_assets_status_checker.rb
Removed OSS path-resolver methods for RSC; updated server_bundle? and asset-resolution logic to be Pro-aware and delegate to Pro utils when available; centralized asset-path resolution in test helper.
OSS: tests updated/removed
spec/react_on_rails/*, spec/dummy/*
Removed RSC configuration tests from OSS and updated tests to stub or delegate to Pro utilities where relevant.
Pro: configuration added
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb, react_on_rails_pro/docs/configuration.md, react_on_rails_pro/spec/dummy/config/initializers/*
Added RSC config attrs and defaults in Pro: rsc_bundle_js_file, react_client_manifest_file, react_server_client_manifest_file; updated docs and dummy initializers.
Pro: streaming helpers implemented
react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb
Implemented streaming APIs (stream_react_component, rsc_payload_react_component) and internal fiber/stream/NDJSON chunk assembly and streaming result builders.
Pro: RSC utilities implemented
react_on_rails_pro/lib/react_on_rails_pro/utils.rb
Added rsc_bundle_js_file_path, react_client_manifest_file_path, react_server_client_manifest_file_path, and rsc_support_enabled? with caching/validation.
Pro: code callsite switches
react_on_rails_pro/lib/react_on_rails_pro/request.rb, react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb
Switched RSC asset/manifest lookups and render-path reads to use ReactOnRailsPro::Utils / ReactOnRailsPro.configuration.
Pro: tests & specs added/expanded
react_on_rails_pro/spec/**/*_spec.rb
Added/expanded tests for Pro RSC configuration, utilities, streaming behavior; adjusted spec helpers and logging.
Docs & changelogs
CHANGELOG.md, docs/api-reference/*.md, react_on_rails_pro/CHANGELOG.md
Removed detailed RSC/streaming docs from OSS, added migration notes and Pro-only docs/changelog entries describing moved configs and helpers.

Sequence Diagram(s)

sequenceDiagram
    participant OSS as ReactOnRails (OSS)
    participant PRO as ReactOnRailsPro (Pro)
    participant CFG as Configuration

    rect rgb(245,250,255)
    Note over OSS,PRO: Asset/path detection and delegation
    OSS->>OSS: need to check server bundle or RSC support
    OSS->>PRO: react_on_rails_pro? / rsc_support_enabled? (delegation)
    alt Pro present
        PRO->>CFG: read rsc_* config values
        CFG-->>PRO: rsc paths & enable flag
        PRO-->>OSS: support=true, paths
    else Pro absent
        OSS-->>OSS: support=false, use OSS-only logic
    end
    end

    rect rgb(235,255,235)
    Note over PRO: Streaming/rendering (Pro-only)
    Client->>PRO: request stream_react_component / rsc_payload_react_component
    PRO->>PRO: run_stream_inside_fiber -> internal_*_stream...
    PRO->>PRO: build initial chunk + hydration metadata + subsequent chunks (NDJSON for RSC payload)
    PRO-->>Client: streamed response (HTML or NDJSON)
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • alexeyr-ci
  • justin808
  • Judahmeek

Poem

🐰 I hopped through code to make a seam,

Took streaming rivers to a Pro-only stream.
OSS now lighter, Pro holds the sparks,
Manifests and bundles tucked in dark.
Hop — configs found a finer home tonight.

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes Check ⚠️ Warning The PR introduces one out-of-scope change: the addition of .claude/.fuse_hidden* to .gitignore. This pattern is unrelated to the objective of moving Pro-specific utilities and configurations, and appears to be a development environment artifact (Claude IDE cache) rather than a legitimate part of the feature work. While most changes directly support the PR's objectives of separating Pro code from open-source, this gitignore entry should not have been included in this PR. Remove the .claude/.fuse_hidden* line from the .gitignore changes. This entry is unrelated to the PR's core objective and appears to be a developer environment-specific addition that should be handled separately (either committed to a personal gitignore configuration or added in a separate housekeeping PR if appropriate for the project).
Docstring Coverage ⚠️ Warning Docstring coverage is 27.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The PR title "Move Pro-specific utilities and configurations to Pro gem" is clear, concise, and directly describes the primary objective of the changeset. It accurately summarizes the main work being done—migrating Pro-specific code from the open-source gem to the Pro gem—in a way that a teammate scanning the repository history would immediately understand. The title is neither vague nor overly broad, and it avoids noise while conveying the essential change.
Linked Issues Check ✅ Passed The PR addresses the primary objectives outlined in issue #1874 by removing Pro-specific code from the open-source gem and relocating it to the Pro gem. The changes successfully move RSC configuration options (rsc_bundle_js_file, react_server_client_manifest_file, react_client_manifest_file) to ReactOnRailsPro::Configuration [#1874], migrate RSC utility methods (rsc_support_enabled?, rsc_bundle_js_file_path, etc.) to ReactOnRailsPro::Utils [#1874], and relocate streaming helper methods (stream_react_component, rsc_payload_react_component) to the Pro gem's helpers [#1874]. Core open-source functionality that should remain—such as react_component, react_component_hash, and core configuration options—continues to be preserved. Documentation and tests have been updated consistently across both gems to reflect the reorganization [#1874].
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch move-pro-utils-and-configs-to-pro-gem

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a377cac and 24fb4bc.

📒 Files selected for processing (1)
  • lib/react_on_rails/test_helper/webpack_assets_status_checker.rb (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/react_on_rails/test_helper/webpack_assets_status_checker.rb
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (11)
  • GitHub Check: claude-review
  • GitHub Check: rspec-package-tests (3.4, minimum)
  • GitHub Check: rspec-package-tests (3.4, latest)
  • GitHub Check: build-dummy-app-webpack-test-bundles (3.2, 20)
  • GitHub Check: rspec-package-tests (3.2, minimum)
  • GitHub Check: rspec-package-tests (3.2, latest)
  • GitHub Check: build
  • GitHub Check: lint-js-and-ruby
  • GitHub Check: markdown-link-check
  • GitHub Check: build-dummy-app-webpack-test-bundles
  • GitHub Check: build-dummy-app-webpack-test-bundles

Comment @coderabbitai help to get the list of available commands and usage tips.

Add tests for the three RSC utility methods moved to Pro gem:

- rsc_support_enabled?: Tests enabled/disabled states
- rsc_bundle_js_file_path: Tests delegation to bundle_js_file_path,
  caching behavior in development vs production
- react_client_manifest_file_path: Tests packer integration with
  dev server running/not running, caching behavior
- react_server_client_manifest_file_path: Tests delegation,
  caching behavior, error handling when manifest is nil

Total: ~210 lines of tests ensuring all RSC utility methods work
correctly in the Pro gem with proper caching and error handling.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@AbanoubGhadban AbanoubGhadban force-pushed the move-pro-utils-and-configs-to-pro-gem branch from d81bb5e to a978ea6 Compare October 23, 2025 11:09
@claude
Copy link

claude bot commented Oct 23, 2025

Code Review: Move Pro-specific utilities and configurations to Pro gem

Thank you for this well-structured refactoring! This PR successfully moves React Server Components (RSC) and streaming-related configurations and utilities from the open-source gem to the Pro gem, improving separation of concerns. Here's my detailed review:

✅ Strengths

  1. Excellent Documentation

    • Comprehensive CHANGELOG entries in both gems clearly documenting breaking changes
    • Detailed migration guide with before/after examples
    • Updated API documentation to indicate Pro-only features
    • Clear phase-based implementation plan in PR description
  2. Good Code Organization

    • Clean separation of RSC configurations into Pro gem
    • Proper delegation pattern maintained (Pro utilities calling base utilities)
    • Configuration defaults properly defined in Configuration class constants
  3. Strong Test Coverage

    • Comprehensive test suite added for moved utilities (react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb)
    • Tests for RSC bundle paths, manifest paths, and caching behavior
    • Tests removed from open-source gem appropriately
  4. Backward Compatibility Handling

    • Conditional checks for Pro gem availability (ReactOnRails::Utils.react_on_rails_pro?)
    • Graceful degradation in packer_utils.rb:61-63 and utils.rb:236-240

🔍 Potential Issues & Concerns

1. Caching Logic Inconsistency (lib/react_on_rails_pro/utils.rb:22-27)

The RSC bundle path caching doesn't reset instance variables properly:

def self.rsc_bundle_js_file_path
  return @rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?

  bundle_name = ReactOnRailsPro.configuration.rsc_bundle_js_file
  @rsc_bundle_path = ReactOnRails::Utils.bundle_js_file_path(bundle_name)
end

Issue: If bundle_js_file_path raises an exception, @rsc_bundle_path will be set to nil but cached. Subsequent calls will return nil instead of retrying.

Recommendation: Consider adding error handling or resetting cache on failure.

2. Missing .fuse_hidden File (.claude/.fuse_hidden000017da00000005)

This appears to be a temporary FUSE filesystem file that shouldn't be committed:

Recommendation: Add to .gitignore and remove from this PR. This file contains permission configurations that seem unrelated to the PR's purpose.

3. Potential Race Condition in Test Specs (react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb)

Tests manipulate class instance variables (@rsc_bundle_path, @react_client_manifest_path) which could cause flaky tests if run in parallel:

before do
  described_class.instance_variable_set(:@rsc_bundle_path, nil)
end

Recommendation: Consider using RSpec's around hooks or ensuring tests are not parallelized for this spec file.

4. Incomplete Implementation (As noted in PR description)

The PR is marked [WIP] with several phases incomplete:

  • Phase 3-11 are not yet implemented
  • Streaming helper methods (stream_react_component, rsc_payload_react_component) mentioned in CHANGELOG as "moved" but actual move not visible in diff

Question: Should this PR be reviewed/merged as-is, or should it wait for completion of all phases?

🐛 Potential Bugs

1. Error Message Inconsistency (react_on_rails_pro/lib/react_on_rails_pro/utils.rb:43-44)

raise ReactOnRailsPro::Error,
      "react_server_client_manifest_file is nil, ensure it is set in your configuration"

The error doesn't specify it should be set in ReactOnRailsPro.configure (not ReactOnRails.configure).

Recommendation: Update error message to:

"react_server_client_manifest_file is nil, ensure it is set in ReactOnRailsPro.configure"

2. Missing Guard in contains_hash? (react_on_rails_pro/lib/react_on_rails_pro/utils.rb:152-156)

def self.contains_hash?(server_bundle_basename)
  ReactOnRails.configuration.server_bundle_js_file != server_bundle_basename &&
    ReactOnRailsPro.configuration.rsc_bundle_js_file != server_bundle_basename
end

This assumes ReactOnRailsPro.configuration is always available. If Pro gem isn't loaded, this will fail.

Recommendation: Add nil check:

def self.contains_hash?(server_bundle_basename)
  ReactOnRails.configuration.server_bundle_js_file != server_bundle_basename &&
    (defined?(ReactOnRailsPro) ? ReactOnRailsPro.configuration.rsc_bundle_js_file != server_bundle_basename : true)
end

🔒 Security Considerations

No security issues identified. The changes are configuration-related and don't introduce new attack vectors.

⚡ Performance Considerations

  1. Caching Strategy - Good caching implementation for production environments
  2. Development Mode - Appropriate cache bypassing in development for hot-reloading
  3. No performance regressions expected - The changes move code without altering algorithms

📋 Test Coverage Assessment

Overall: Good

✅ Added comprehensive tests for:

  • rsc_bundle_js_file_path
  • react_client_manifest_file_path
  • react_server_client_manifest_file_path
  • rsc_support_enabled?
  • Caching behavior in development vs production

❌ Missing tests for:

  • Error handling when bundle files don't exist
  • Error message clarity when configuration is missing
  • Integration tests for open-source gem working without Pro features

📝 Code Quality & Best Practices

Positives:

  • ✅ Follows repository conventions (RuboCop compliant expected)
  • ✅ Good use of memoization for performance
  • ✅ Clear method naming and documentation
  • ✅ Proper use of frozen_string_literal: true

Suggestions:

  1. Remove commented code (react_on_rails_pro/lib/react_on_rails_pro/utils.rb:3-7)
  2. Add YARD documentation for public API methods
  3. Consider extracting constants for error messages to make them easier to test and maintain

🎯 Recommendations

High Priority:

  1. ❗ Remove .claude/.fuse_hidden000017da00000005 file
  2. ❗ Fix error message in react_server_client_manifest_file_path to specify ReactOnRailsPro.configure
  3. ❗ Add nil guard in contains_hash? method
  4. ❗ Clarify PR status - is this ready for review or should it wait for completion?

Medium Priority:

  1. Add error handling for failed bundle path lookups
  2. Add integration tests ensuring open-source gem works without Pro features
  3. Remove commented-out code

Low Priority:

  1. Add YARD documentation for public methods
  2. Extract error message constants
  3. Review test parallelization strategy

✨ Overall Assessment

This is a well-executed refactoring with clear goals, good documentation, and solid test coverage. The architectural decision to move Pro features to the Pro gem is sound and improves maintainability.

Status: The PR shows high code quality but appears incomplete (WIP). Once the .fuse_hidden file is removed, error messages are clarified, and nil guards are added, the completed work (Phases 1-2) would be merge-ready.

Recommendation:

  • If Phases 1-2 should be merged separately, address the high-priority issues and merge
  • If all phases should be completed first, continue with Phase 3+ before final review

Great work on the migration strategy and documentation! 🚀


Review generated by Claude Code

Fix the rsc_support_enabled? method to return true/false instead of nil
when enable_rsc_support is false or nil.

Issue: The expression `respond_to?(:enable_rsc_support) && enable_rsc_support`
returns nil when enable_rsc_support is falsy, not an explicit false.

Solution: Use double bang (!!) to coerce the result to a boolean:
`respond_to?(:enable_rsc_support) && !!enable_rsc_support`

This fixes 3 failing tests:
- ReactOnRailsPro::Utils.rsc_support_enabled? when RSC support is enabled
- ReactOnRailsPro::Utils.rsc_support_enabled? when RSC support is disabled
- ReactOnRailsPro::Utils cache helpers .bundle_hash and .bundle_file_name

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link

claude bot commented Oct 23, 2025

Code Review: Move Pro-specific utilities and configurations to Pro gem

Overall Assessment

This is a well-structured refactoring that clearly separates Pro-only features from the open-source gem. The migration is comprehensive and follows good practices for breaking changes. The code quality is excellent with proper test coverage.

✅ Strengths

1. Excellent Documentation

  • Clear migration path in both CHANGELOGs with before/after examples
  • Updated API reference docs to point users to Pro documentation
  • Well-organized phase checklist in PR description

2. Strong Test Coverage

  • All moved configurations have corresponding spec tests in Pro gem
  • Tests verify default values, custom values, and nil handling
  • Caching behavior properly tested for RSC utility methods
  • Edge cases covered (e.g., nil manifest file raises error)

3. Clean Code Architecture

  • Proper delegation pattern: ReactOnRails::Utils.rsc_support_enabled? delegates to ReactOnRailsPro::Utils
  • Maintains backward compatibility where needed
  • Clear separation of concerns between open-source and Pro

4. Good Error Handling

  • Proper error messages for nil configurations
  • Conditional checks for Pro availability before accessing Pro config

🔍 Issues Found

1. Potential Bug in webpack_assets_status_checker.rb:53-66

Issue: Missing Pro availability check before accessing Pro config:

if ReactOnRails::Utils.react_on_rails_pro?
  pro_config = ReactOnRailsPro.configuration
  if bundle_name == pro_config.react_client_manifest_file

Problem: This code checks react_on_rails_pro? but still tries to access ReactOnRailsPro.configuration which may not be defined if Pro gem isn't loaded.

Recommendation: Add a check for defined?(ReactOnRailsPro):

if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
  pro_config = ReactOnRailsPro.configuration
  # ... rest of logic

2. Inconsistent Pro Detection Pattern

In lib/react_on_rails/packer_utils.rb:61-62:

if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
  is_bundle_running_on_server ||= (bundle_name == ReactOnRailsPro.configuration.rsc_bundle_js_file)

In lib/react_on_rails/utils.rb:158-161:

if react_on_rails_pro?
  pro_config = ReactOnRailsPro.configuration
  return true if bundle_name == pro_config.rsc_bundle_js_file ||

Recommendation: Use consistent pattern across all files. The safer pattern is:

if react_on_rails_pro? && defined?(ReactOnRailsPro)

3. Missing RuboCop Validation

Per CLAUDE.md requirements:

  • CRITICAL: Must run bundle exec rubocop before commit
  • ⚠️ CRITICAL: Files must end with newline character

Recommendation:

bundle exec rubocop

Check all modified Ruby files end with a newline.

🎯 Best Practices Compliance

Following CLAUDE.md Guidelines ✅

  • Code changes are logical and well-structured
  • Tests added for new functionality
  • MUST RUN: bundle exec rubocop (required before merge)
  • VERIFY: All files end with newline character

Code Quality ✅

  • Clean separation of concerns
  • Proper use of memoization with cache invalidation in development
  • Good delegation patterns
  • Proper error messages

📋 Recommendations

High Priority

  1. Fix Pro availability checks - Ensure all Pro config access is guarded by both react_on_rails_pro? AND defined?(ReactOnRailsPro)

  2. Run RuboCop - This is mandatory per project guidelines:

    bundle exec rubocop
  3. Verify trailing newlines - All files must end with newline character

Medium Priority

  1. Consider extracting Pro detection helper - To ensure consistency:

    def self.pro_available?
      react_on_rails_pro? && defined?(ReactOnRailsPro)
    end
  2. Verify removed constants - Ensure no other code references the removed constants:

    DEFAULT_REACT_CLIENT_MANIFEST_FILE
    DEFAULT_REACT_SERVER_CLIENT_MANIFEST_FILE
    
  3. Test open-source gem without Pro - Verify the gem works correctly when Pro is not installed

Low Priority

  1. .gitignore entry - The .claude/.fuse_hidden* entry is fine but seems unrelated to this PR

🔒 Security Considerations

  • ✅ No security concerns identified
  • ✅ Server bundle privacy enforcement logic remains intact
  • ✅ Pro features properly gated behind Pro detection

🎬 Next Steps

Based on the PR description, this is Phase 2 of 11. The implementation looks solid, but please:

  1. ✅ Run bundle exec rubocop and fix all violations (MANDATORY)
  2. ✅ Fix the Pro availability check inconsistencies
  3. ✅ Verify all files end with newlines (MANDATORY)
  4. Test that open-source gem works without Pro installed
  5. Proceed to Phase 3 with confidence

Summary

Verdict: Approve with minor fixes required

This is excellent refactoring work with proper separation of concerns and good test coverage. The only blockers are:

  • Fix Pro availability checks in webpack_assets_status_checker.rb
  • Run bundle exec rubocop (mandatory per CLAUDE.md)
  • Verify trailing newlines (mandatory per CLAUDE.md)

Great job on the comprehensive migration plan! 🚀

Moved all streaming-related helper methods from open-source to Pro gem:

Public methods moved to ReactOnRailsProHelper:
- stream_react_component - Progressive SSR using React 18+ streaming
- rsc_payload_react_component - RSC payload rendering with NDJSON format

Private methods moved to ReactOnRailsProHelper:
- run_stream_inside_fiber - Fiber management for streaming context
- internal_stream_react_component - Internal HTML streaming implementation
- internal_rsc_payload_react_component - Internal RSC payload implementation
- build_react_component_result_for_server_streamed_content - Stream chunk transformation

Changes:
- Removed 6 streaming methods from lib/react_on_rails/helper.rb (~162 lines)
- Added 6 streaming methods to react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb (+176 lines)
- Added RuboCop ModuleLength disable/enable for Pro helper module
- No backward compatibility (clean removal per requirements)

All methods remain accessible through Rails helper inclusion mechanism.
Comprehensive test coverage exists in Pro helper spec.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link

claude bot commented Oct 23, 2025

Comprehensive Code Review - PR #1875

I've completed a thorough review of this pull request. Overall, this is a well-structured refactoring that successfully moves Pro-specific features to the Pro gem. Here's my detailed feedback:


Code Quality & Architecture

Strengths:

  1. Clear Separation of Concerns: The migration cleanly separates Pro features from the open-source gem, making the codebase more maintainable and the feature boundaries explicit.

  2. Well-Documented Migration Path: The CHANGELOG entries in both gems provide clear before/after examples, making it easy for users to migrate their configurations.

  3. Backward Compatibility Handling: The code properly checks for Pro availability before accessing Pro configurations (e.g., in packer_utils.rb:60-63 and utils.rb:116-120).

  4. Consistent Patterns: The moved methods maintain consistent signatures and behavior in the Pro gem, reducing the risk of breaking existing functionality.

Recommendations:

  1. Doctor.rb Still References Old Config (lib/react_on_rails/doctor.rb:679,681):

    • The Doctor diagnostic tool still references config.rsc_bundle_js_file from the ReactOnRails configuration
    • This should be updated to check ReactOnRailsPro.configuration.rsc_bundle_js_file when Pro is available
    • Consider: Add a check for Pro availability and reference the correct configuration namespace
  2. Gitignore Entry (.gitignore:78):

    • Added .claude/.fuse_hidden* - this appears to be a development artifact
    • Consider: Remove this from the PR as it's not related to the core changes

🐛 Potential Issues

High Priority:

  1. Missing Delegation in Helper (lib/react_on_rails/helper.rb):
    • The stream_react_component and rsc_payload_react_component methods were removed from the open-source gem
    • If users accidentally call these methods without Pro, they'll get a confusing NoMethodError
    • Recommendation: Add helpful error messages that direct users to upgrade to Pro:
def stream_react_component(component_name, options = {})
  raise ReactOnRails::Error, 
    "stream_react_component is a React on Rails Pro feature. " \
    "Please visit https://www.shakacode.com/react-on-rails-pro for licensing information."
end

Medium Priority:

  1. Caching Variables Not Reset (react_on_rails_pro/lib/react_on_rails_pro/utils.rb:22-48):

    • The caching instance variables @rsc_bundle_path, @react_client_manifest_path, and @react_server_manifest_path are used but there's no clear mechanism to reset them between tests
    • This could cause test pollution in the test suite
    • Recommendation: Consider adding a reset method for testing or document the caching behavior
  2. Double Bang Coercion (react_on_rails_pro/lib/react_on_rails_pro/utils.rb:54):

    • Uses !!rorp_config.enable_rsc_support to coerce to boolean
    • This is safe but could be more explicit: rorp_config.enable_rsc_support == true

Performance Considerations

Positive:

  1. Appropriate Caching: The configuration utilities properly cache file paths in production while allowing development mode to refresh on each request
  2. No Performance Regression: The conditional Pro checks (react_on_rails_pro?) are lightweight and won't impact performance

Note:

  • The bundle_js_file_path lookups remain efficient with proper caching strategies in place

🔒 Security Concerns

All Clear:

  1. ✅ No credential exposure or security vulnerabilities introduced
  2. ✅ Configuration validation properly maintained in Pro gem (configuration.rb:110-129)
  3. ✅ The enforce_private_server_bundles security feature correctly remains in open-source

🧪 Test Coverage & Migration

Concerns:

  1. Phase Progress: The PR shows only Phase 1 and 2 are complete. Key phases still pending:

    • Phase 3: RSC Utility Methods
    • Phase 4: Streaming Helper Methods
    • Phase 8: Doctor Diagnostics (mentioned above)
  2. Test Files Not Updated: The diff doesn't show updates to test files that may reference the old configuration paths

    • Check: spec/react_on_rails/utils_spec.rb
    • Check: Open-source tests that might be testing Pro features
  3. Migration Testing:

    • Recommendation: Add integration tests that verify the open-source gem works correctly without Pro installed
    • Recommendation: Add tests that verify proper error messages when Pro features are called without Pro

📋 Additional Recommendations

  1. Documentation Links: Update references in error messages and docs to point to the new Pro configuration documentation

  2. Deprecation Warning (Optional): Consider adding a deprecation warning if users still have the old config in ReactOnRails.configure to help them discover the change:

# In ReactOnRails::Configuration#initialize
if rsc_bundle_js_file.present?
  warn "DEPRECATION WARNING: rsc_bundle_js_file should be configured in ReactOnRailsPro.configure, not ReactOnRails.configure"
end
  1. Version Compatibility Check: The Pro gem already has check_react_on_rails_support_for_rsc (configuration.rb:120-129), which is excellent. Ensure this version check is strict enough.

📊 Summary

Category Status Notes
Architecture ✅ Excellent Clean separation, well-organized
Code Quality ✅ Good Clear, maintainable code
Documentation ✅ Good Clear migration path
Backward Compat ⚠️ Needs Work Add helpful error messages
Security ✅ Clear No concerns
Tests ⚠️ In Progress WIP - phases incomplete
Performance ✅ Good No regressions

Overall Assessment: This is a well-executed refactoring that properly separates Pro features. The main concerns are:

  1. Completing the remaining phases (especially Doctor diagnostics)
  2. Adding helpful error messages for users who call Pro methods without Pro
  3. Ensuring comprehensive test coverage for the migration

Recommendation: Address the Doctor.rb references and error message improvements before merging. The incomplete phases should be finished according to the checklist in the PR description.


Great work on this refactoring! The separation is clean and the migration path is well-documented. 🚀

AbanoubGhadban and others added 2 commits October 23, 2025 17:13
Critical bugfix discovered during code review:
- Lines 67-68 were still calling ReactOnRails.configuration instead of ReactOnRailsPro.configuration
- Updated to use ReactOnRailsPro.configuration.react_client_manifest_file
- Updated to use ReactOnRailsPro.configuration.react_server_client_manifest_file
- Extracted config to local variable to fix RuboCop line length violation

This ensures RSC manifest file configurations are read from the correct Pro configuration
after they were moved from open-source to Pro gem in Phase 2.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed 3 test failures in utils_spec.rb that were caused by mocking
non-existent ReactOnRails.configuration.rsc_bundle_js_file.

Changes:
- Updated tests to mock ReactOnRailsPro.configuration instead
- Added proper Pro gem presence mocking with stub_const
- Tests now correctly verify open-source bundle_js_file_path behavior
  when RSC bundles are present with Pro gem installed
- Applied RuboCop auto-corrections for style compliance

The open-source bundle_js_file_path function correctly handles RSC bundles
by checking Pro configuration (lines 117-121 in utils.rb), so these tests
ensure that behavior works as expected.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link

claude bot commented Oct 23, 2025

Code Review for PR #1875: Move Pro-specific utilities and configurations to Pro gem

I've completed a comprehensive review of this PR. Overall, this is a well-structured refactoring that successfully separates Pro features from the open-source gem. However, I've identified several critical issues that need to be addressed before merging.


Critical Issues

1. BREAKING BUG: Undefined Method References in Configuration (lib/react_on_rails/configuration.rb:319-321)

Location: lib/react_on_rails/configuration.rb:313-323

This method references rsc_bundle_js_file, react_client_manifest_file, and react_server_client_manifest_file which were removed from the Configuration class. These are no longer attr_accessors on the open-source configuration.

Impact: This will cause NoMethodError exceptions when webpack_generated_files is empty and the configuration is initialized.

Recommended Fix: Update the ensure_webpack_generated_files_exists method to conditionally add Pro manifest files only when Pro is available, checking ReactOnRails::Utils.react_on_rails_pro? and accessing ReactOnRailsPro.configuration.


2. Test Compatibility Issues: Tests Still Reference Removed Configuration

Location: spec/react_on_rails/utils_spec.rb:62, 99-101

The tests still mock the removed configuration attributes. These tests will fail because these configuration options no longer exist on ReactOnRails.configuration.

Recommended Fix: Update these tests to mock ReactOnRailsPro.configuration instead, with proper Pro gem availability checks.


3. Doctor Diagnostics Still Look for Old Configuration

Location: lib/react_on_rails/doctor.rb:679-681

The doctor is still looking for config.rsc_bundle_js_file in ReactOnRails.configure blocks, but this should now be in ReactOnRailsPro.configure blocks.

Recommended Fix: Update the doctor to look for RSC configs in ReactOnRailsPro.configure blocks and warn if found in the old location with migration guidance.


Code Quality & Best Practices

Excellent Architectural Decisions

✅ Proper separation of concerns: RSC features are now clearly in the Pro gem where they belong

✅ Good use of feature detection: The code properly checks for Pro gem availability before accessing Pro configs

✅ Clean delegation: ReactOnRails::Utils.rsc_support_enabled? properly delegates to ReactOnRailsPro::Utils.rsc_support_enabled?

✅ Documentation is thorough: Both CHANGELOGs are well-documented with migration examples

✅ Pro utility methods were properly moved with good comments explaining the migration


Performance & Security

No Performance Concerns - The changes don't introduce any performance regressions. The conditional Pro checks add minimal overhead and are appropriately cached.

No Security Issues - The security model remains the same. Server bundle privacy enforcement (enforce_private_server_bundles) correctly stays in the open-source gem.


Test Coverage Assessment

  • ✅ Pro specs appear to be updated
  • ❌ Open-source specs need updates (mocking non-existent configs)
  • ⚠️ Integration tests between OSS and Pro gems should be verified

Recommendations:

  1. Fix failing tests in spec/react_on_rails/utils_spec.rb
  2. Add integration tests to ensure Pro features work correctly when Pro gem is loaded
  3. Test the error path when Pro configs are accessed without Pro gem installed
  4. Verify all dummy app tests pass (both open-source and Pro dummy apps)

Documentation Quality

Strengths:

  • ✅ Comprehensive CHANGELOG entries in both gems
  • ✅ Clear migration path documented
  • ✅ Updated API reference docs
  • ✅ Good inline comments explaining the migration

Suggestions:

  • Add a migration guide document (separate from CHANGELOG) for Pro users upgrading
  • Update any generator templates that might reference the old configs
  • Consider adding method_missing in Configuration to provide helpful error messages when users try to set deprecated configs

Final Recommendations

Must Fix Before Merge:

  1. Fix the critical bug in ensure_webpack_generated_files_exists (Issue TODO for first version #1)
  2. Update failing tests to use Pro configuration (Issue Make work with turbolinks and better helper #2)
  3. Update doctor diagnostics to check Pro configs (Issue Add linting and CI scripts #3)

Should Fix:

  1. Add helpful error messages for deprecated configurations
  2. Verify view helper implementations in Pro gem (diff was truncated)
  3. Add integration test coverage

Nice to Have:

  1. Create a dedicated migration guide document
  2. Add deprecation warnings if old configs are detected

Overall Assessment

Architecture: ⭐⭐⭐⭐⭐ Excellent separation of concerns

Implementation: ⭐⭐⭐⚠️ Good but has critical bugs that must be fixed

Documentation: ⭐⭐⭐⭐ Very thorough

Test Coverage: ⭐⭐⭐ Adequate but needs fixes

Migration Path: ⭐⭐⭐⭐ Well-documented but could use runtime guidance


Verdict: This is a valuable refactoring that improves the codebase architecture. However, the critical bug in ensure_webpack_generated_files_exists must be fixed before merging, along with the test updates. Once these issues are resolved, this will be ready to merge.

Great work on the thorough documentation and systematic approach! The phased checklist in the PR description shows excellent planning.

AbanoubGhadban and others added 2 commits October 23, 2025 17:33
Added inline RuboCop disable comment for the Pro configuration double
since we're mocking a module from the Pro gem that doesn't exist in the
open-source test environment. Using a regular double is appropriate here.

Changes:
- Reverted complex instance_double setup
- Added `# rubocop:disable RSpec/VerifiedDoubles` inline comment
- RuboCop now passes with 0 offenses

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
Fixed test failures caused by attempting to mock configuration on an
empty Module stub. The stubbed ReactOnRailsPro module now properly
implements the configuration getter/setter methods.

Changes:
- Created proper mock Pro module with working configuration methods
- Set configuration directly instead of using allow().to receive()
- Matches the real Pro gem's module structure

This fixes 4 test failures:
- returns private path when it exists even if public path also exists
- fallbacks to public path when private path does not exist and public path exists
- returns configured path if both private and public paths do not exist
- enforces private RSC bundles and never checks public directory

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
@claude
Copy link

claude bot commented Oct 23, 2025

PR Review: Move Pro-specific utilities and configurations to Pro gem

Thank you for working on this important refactoring! This is a well-structured migration that improves code separation between the open-source and Pro versions. Here's my detailed review:


🐛 Critical Bug

1. Undefined method references in ensure_webpack_generated_files_exists (lib/react_on_rails/configuration.rb:319-321)

Issue: The method references rsc_bundle_js_file, react_client_manifest_file, and react_server_client_manifest_file which were removed from the ReactOnRails::Configuration class.

Location: lib/react_on_rails/configuration.rb:313-323

def ensure_webpack_generated_files_exists
  return unless webpack_generated_files.empty?

  self.webpack_generated_files = [
    "manifest.json",
    server_bundle_js_file,
    rsc_bundle_js_file,                    # ❌ NoMethodError - removed from config
    react_client_manifest_file,            # ❌ NoMethodError - removed from config
    react_server_client_manifest_file      # ❌ NoMethodError - removed from config
  ].compact_blank
end

Impact: This will cause a runtime error (NoMethodError) when the configuration is initialized with an empty webpack_generated_files array.

Fix Required: Remove the Pro-specific references or check for Pro availability:

def ensure_webpack_generated_files_exists
  return unless webpack_generated_files.empty?

  files = ["manifest.json", server_bundle_js_file]
  
  # Add Pro-specific files if Pro is available
  if ReactOnRails::Utils.react_on_rails_pro?
    pro_config = ReactOnRailsPro.configuration
    files.concat([
      pro_config.rsc_bundle_js_file,
      pro_config.react_client_manifest_file,
      pro_config.react_server_client_manifest_file
    ])
  end
  
  self.webpack_generated_files = files.compact_blank
end

✅ Positive Aspects

  1. Clean separation of concerns - RSC configurations properly moved to Pro gem
  2. Good documentation - CHANGELOG entries clearly explain the migration path
  3. Backward compatibility - Proper checks for Pro availability using ReactOnRails::Utils.react_on_rails_pro?
  4. Comprehensive test removal - RSC-related tests properly removed from open-source specs
  5. Well-structured migration - Pro helper methods properly moved to ReactOnRailsPro::Utils

🔍 Code Quality Observations

Good Patterns

  1. Conditional Pro checks in packer_utils.rb:58-62:

    # Check Pro RSC bundle if Pro is available
    if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
      is_bundle_running_on_server ||= (bundle_name == ReactOnRailsPro.configuration.rsc_bundle_js_file)
    end

    This safely handles the case when Pro is not installed.

  2. Proper configuration defaults in Pro gem:

    DEFAULT_RSC_BUNDLE_JS_FILE = "rsc-bundle.js"
    DEFAULT_REACT_CLIENT_MANIFEST_FILE = "react-client-manifest.json"
    DEFAULT_REACT_SERVER_CLIENT_MANIFEST_FILE = "react-server-client-manifest.json"
  3. Documentation updates clearly distinguish Pro features in docs/api-reference/view-helpers-api.md


📝 Suggestions

1. Test Coverage

The critical bug should be caught by tests. Consider adding a test case:

# In spec/react_on_rails/configuration_spec.rb
it "properly populates webpack_generated_files without Pro" do
  ReactOnRails.configure do |config|
    config.webpack_generated_files = []
  end
  
  # Should not raise NoMethodError
  expect { ReactOnRails.configuration.setup_config_values }.not_to raise_error
  expect(ReactOnRails.configuration.webpack_generated_files).to include("manifest.json")
end

2. Breaking Change Communication

The CHANGELOG is excellent, but consider:

  • Adding a deprecation warning if users have these configs in their ReactOnRails.configure block before the actual migration
  • This could help users discover the issue before upgrading

3. Code Consistency

In webpack_assets_status_checker.rb:50-64, the logic checks for Pro but could be simplified:

def all_compiled_assets
  @all_compiled_assets ||= begin
    webpack_generated_files = @webpack_generated_files.map do |bundle_name|
      # Delegate to appropriate config based on bundle type
      if ReactOnRails::Utils.react_on_rails_pro? && pro_manifest_file?(bundle_name)
        resolve_pro_manifest_path(bundle_name)
      else
        ReactOnRails::Utils.bundle_js_file_path(bundle_name)
      end
    end
    # ... rest of logic
  end
end

def pro_manifest_file?(bundle_name)
  pro_config = ReactOnRailsPro.configuration
  [pro_config.react_client_manifest_file, 
   pro_config.react_server_client_manifest_file].include?(bundle_name)
end

🔒 Security & Performance

  • ✅ No security concerns identified
  • ✅ Performance impact minimal - configuration changes are initialization-time only
  • ✅ No credential or sensitive data handling issues

📋 Completeness Check

Based on the PR description's phase checklist:

  • ✅ Phase 1: Documentation updated
  • ✅ Phase 2: RSC configs moved (but has the critical bug above)
  • ❌ Phase 3-11: Marked as incomplete (expected for WIP)

Recommendations

Must Fix Before Merge

  1. Fix the ensure_webpack_generated_files_exists method to avoid NoMethodError
  2. ⚠️ Add test coverage for the configuration without Pro gem installed
  3. ⚠️ Verify CI passes with the fix

Nice to Have

  • Consider adding a migration guide in the docs
  • Add integration tests that verify the gem works correctly without Pro installed
  • Consider deprecation warnings for smoother migration

Summary

This is a well-thought-out refactoring with one critical bug that needs to be fixed before merging. The overall architecture and migration approach are solid. Once the ensure_webpack_generated_files_exists issue is resolved and tested, this will be a clean separation of Pro features from the open-source gem.

Recommendation: Request changes due to the critical bug, but the overall direction is excellent! 👍


Review completed following repository guidelines from CLAUDE.md and project conventions.

@claude
Copy link

claude bot commented Oct 23, 2025

Code Review - PR #1875: Move Pro-specific utilities and configurations to Pro gem

Overview

This is a well-structured WIP PR that migrates RSC-specific configurations from the open-source gem to the Pro gem. The implementation demonstrates good architectural separation and maintains backward compatibility where appropriate.

✅ Strengths

1. Excellent Documentation

  • Comprehensive CHANGELOG entries in both gems with clear migration examples
  • Well-documented breaking changes with before/after code examples
  • Helpful inline comments explaining the purpose of RSC configurations
  • Updated API documentation to clearly mark Pro-only features

2. Clean Architectural Separation

  • Proper separation of concerns between open-source and Pro features
  • Conditional checks using ReactOnRails::Utils.react_on_rails_pro? prevent hard dependencies
  • Good use of progressive enhancement pattern - open-source works without Pro

3. Robust Implementation

  • Configuration migration properly handles defaults (lib/react_on_rails_pro/configuration.rb:59-61)
  • Utility methods moved to Pro and properly namespaced (react_on_rails_pro/lib/react_on_rails_pro/utils.rb:22-48)
  • Server bundle detection updated correctly (lib/react_on_rails/utils.rb:112-124)

4. Good Test Coverage

  • RSC config tests removed from open-source and added to Pro specs
  • Configuration specs verify default values and setters
  • Proper test organization following the code migration

🔍 Issues & Recommendations

Critical Issues

1. Potential Bug in webpack_assets_status_checker.rb

Location: lib/react_on_rails/test_helper/webpack_assets_status_checker.rb:52-66

The current implementation has a logical flaw:

webpack_generated_files = @webpack_generated_files.map do |bundle_name|
  # Check if this is a Pro RSC manifest file
  if ReactOnRails::Utils.react_on_rails_pro?
    pro_config = ReactOnRailsPro.configuration
    if bundle_name == pro_config.react_client_manifest_file
      ReactOnRailsPro::Utils.react_client_manifest_file_path
    elsif bundle_name == pro_config.react_server_client_manifest_file
      ReactOnRailsPro::Utils.react_server_client_manifest_file_path
    else
      ReactOnRails::Utils.bundle_js_file_path(bundle_name)
    end
  else
    ReactOnRails::Utils.bundle_js_file_path(bundle_name)
  end
end

Problem: When Pro is NOT available, if someone has these manifest files in their @webpack_generated_files array, they will be treated as regular bundles and passed to ReactOnRails::Utils.bundle_js_file_path, which may not handle them correctly.

Recommendation: Add a guard or warning when Pro-specific files are detected without Pro:

webpack_generated_files = @webpack_generated_files.map do |bundle_name|
  if ReactOnRails::Utils.react_on_rails_pro?
    pro_config = ReactOnRailsPro.configuration
    if bundle_name == pro_config.react_client_manifest_file
      ReactOnRailsPro::Utils.react_client_manifest_file_path
    elsif bundle_name == pro_config.react_server_client_manifest_file
      ReactOnRailsPro::Utils.react_server_client_manifest_file_path
    else
      ReactOnRails::Utils.bundle_js_file_path(bundle_name)
    end
  else
    # Warn if Pro-only files are specified without Pro gem
    pro_manifest_files = ["react-client-manifest.json", "react-server-client-manifest.json"]
    if pro_manifest_files.include?(bundle_name)
      Rails.logger.warn("[ReactOnRails] #{bundle_name} requires React on Rails Pro")
    end
    ReactOnRails::Utils.bundle_js_file_path(bundle_name)
  end
end

Medium Priority Issues

2. Missing Trailing Newlines Check

According to CLAUDE.md, all files must end with a newline character. Please verify:

  • Run: bundle exec rubocop
  • Ensure all modified files have trailing newlines before committing

3. Incomplete Implementation (Expected for WIP)

The PR description shows only Phase 1 & 2 are complete. Before merging:

  • Complete Phases 3-11 as outlined
  • Move streaming helper methods
  • Update doctor diagnostics
  • Update generator templates
  • Verify both dummy apps work correctly

4. Test Coverage Gap

While configuration tests are good, consider adding integration tests for:

  • Behavior when Pro gem is not installed
  • Fallback handling for RSC-related calls without Pro
  • The webpack_assets_status_checker with and without Pro

📝 Minor Suggestions

1. Code Style - Consistent Conditionals

In lib/react_on_rails/packer_utils.rb:58-63:

Current:

is_bundle_running_on_server = bundle_name == ReactOnRails.configuration.server_bundle_js_file

# Check Pro RSC bundle if Pro is available
if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
  is_bundle_running_on_server ||= (bundle_name == ReactOnRailsPro.configuration.rsc_bundle_js_file)
end

Suggestion: The defined?(ReactOnRailsPro) check is redundant if react_on_rails_pro? already verifies Pro availability. Verify if both checks are needed or simplify to one.

2. Documentation Enhancement

In docs/api-reference/configuration.md:104-121, consider adding a link to the issue/PR that explains why these were moved:

# React Server Components and Streaming SSR are Pro features.
# These configurations were moved to Pro in v16.2.0 for better separation.
# See PR #1874 for details.

3. Error Messages

When RSC configs are accessed on open-source gem (if applicable), ensure error messages guide users to Pro documentation.

🔒 Security Review

✅ No security concerns identified:

  • No credential handling
  • No SQL injection risks
  • Proper namespace separation prevents conflicts
  • Configuration changes are backward-compatible for non-Pro users

⚡ Performance Considerations

✅ Performance looks good:

  • Caching in Pro utility methods (@rsc_bundle_path, @react_client_manifest_path)
  • Minimal overhead from conditional Pro checks
  • No N+1 queries or expensive operations introduced

📋 Pre-Merge Checklist

Before marking this PR as ready for review:

  • CRITICAL: Run bundle exec rubocop and fix ALL violations
  • Ensure all files end with newline characters
  • Complete remaining phases (3-11) as outlined in PR description
  • Run full test suite: rake (all tests except examples)
  • Verify both dummy apps work:
    • spec/dummy works without Pro
    • react_on_rails_pro/spec/dummy works with Pro
  • Test with and without Pro gem installed
  • Update CHANGELOG version numbers if needed
  • Consider adding a migration guide in Pro docs

🎯 Overall Assessment

Status: Good foundation, but incomplete (as expected for WIP)

Code Quality: ⭐⭐⭐⭐ (4/5) - Well-structured with one potential bug to fix

Documentation: ⭐⭐⭐⭐⭐ (5/5) - Excellent migration guides and clear explanations

Testing: ⭐⭐⭐ (3/5) - Config tests good, needs integration tests

Recommendation:

  1. Fix the webpack_assets_status_checker issue
  2. Complete remaining phases
  3. Run full lint check before final review
  4. This will be ready to merge once all phases are complete and linting passes

Great work on maintaining backward compatibility and clear separation of concerns! 👍

@claude
Copy link

claude bot commented Oct 23, 2025

Code Review - PR #1875: Move Pro-specific utilities and configurations to Pro gem

Overall, this is a well-executed refactoring that clearly separates Pro features from the open-source gem. The migration path is well-documented, and the architecture is sound. However, I've identified one critical bug that must be fixed before merging, along with several recommendations for improvement.


🔴 Critical Issue - Must Fix

Bug in lib/react_on_rails/configuration.rb:319-322

Location: lib/react_on_rails/configuration.rb:319-322

def ensure_webpack_generated_files_exists
  return unless webpack_generated_files.empty?

  self.webpack_generated_files = [
    "manifest.json",
    server_bundle_js_file,
    rsc_bundle_js_file,           # ❌ UNDEFINED METHOD
    react_client_manifest_file,    # ❌ UNDEFINED METHOD
    react_server_client_manifest_file  # ❌ UNDEFINED METHOD
  ].compact_blank
end

Problem: The Configuration class no longer has these accessor methods after removing the RSC-related attr_accessor declarations (line 70-72). This will cause a NoMethodError when ensure_webpack_generated_files_exists is called.

Impact: This will break the gem initialization for all users (both open-source and Pro), not just those using RSC features.

Fix Required:

def ensure_webpack_generated_files_exists
  return unless webpack_generated_files.empty?

  files = ["manifest.json", server_bundle_js_file]
  
  # Add Pro RSC files if Pro is available and RSC is enabled
  if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
    pro_config = ReactOnRailsPro.configuration
    if pro_config.respond_to?(:rsc_bundle_js_file)
      files.concat([
        pro_config.rsc_bundle_js_file,
        pro_config.react_client_manifest_file,
        pro_config.react_server_client_manifest_file
      ])
    end
  end
  
  self.webpack_generated_files = files.compact_blank
end

⚠️ High Priority Issues

1. Incomplete Test Coverage for Breaking Changes

The configuration specs don't test the removed RSC configurations. You should add tests to verify:

  • That accessing the removed config methods raises appropriate errors
  • That the ensure_webpack_generated_files_exists method works correctly without Pro
  • That it works correctly with Pro installed

Recommendation: Add to spec/react_on_rails/configuration_spec.rb:

describe "RSC configuration removal" do
  it "does not expose rsc_bundle_js_file after migration to Pro" do
    ReactOnRails.configure { |config| }
    expect(ReactOnRails.configuration).not_to respond_to(:rsc_bundle_js_file)
  end
  
  it "generates webpack_generated_files without RSC files when Pro is not available" do
    allow(ReactOnRails::Utils).to receive(:react_on_rails_pro?).and_return(false)
    ReactOnRails.configure { |config| }
    config = ReactOnRails.configuration
    expect(config.webpack_generated_files).to include("manifest.json")
    expect(config.webpack_generated_files).not_to include("rsc-bundle.js")
  end
end

2. Potential Nil Reference in rsc_support_enabled?

Location: lib/react_on_rails/utils.rb:233-241

def self.rsc_support_enabled?
  return false unless react_on_rails_pro?

  ReactOnRailsPro::Utils.rsc_support_enabled?  # May fail if Utils not loaded
end

Issue: If react_on_rails_pro? returns true but ReactOnRailsPro::Utils isn't loaded, this will raise NameError.

Fix:

def self.rsc_support_enabled?
  return false unless react_on_rails_pro?
  return false unless defined?(ReactOnRailsPro::Utils)

  ReactOnRailsPro::Utils.rsc_support_enabled?
end

✅ Positive Aspects

  1. Excellent Documentation: The CHANGELOG entries clearly explain the breaking changes with before/after examples.

  2. Clean Separation of Concerns: The migration properly separates Pro features while maintaining backward compatibility where appropriate.

  3. Consistent Pattern Usage: The code uses consistent patterns for checking Pro availability:

    if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
  4. Well-Structured Migration Guide: The PR description provides a clear roadmap with phases and checklists.

  5. Helper Method Migration: The streaming helpers were properly moved to ReactOnRailsProHelper with correct documentation.


💡 Recommendations

Code Quality

  1. Add Defensive Checks in packer_utils.rb

    Line 61-63 should be more defensive:

    if ReactOnRails::Utils.react_on_rails_pro? && 
       defined?(ReactOnRailsPro) && 
       defined?(ReactOnRailsPro.configuration)
      is_bundle_running_on_server ||= (bundle_name == ReactOnRailsPro.configuration.rsc_bundle_js_file)
    end
  2. DRY Up Pro Configuration Access

    Consider creating a helper method to safely access Pro config:

    def self.pro_configuration
      return nil unless react_on_rails_pro?
      return nil unless defined?(ReactOnRailsPro)
      
      ReactOnRailsPro.configuration
    end

Testing

  1. Add Integration Tests

    • Test the behavior when Pro gem is not installed
    • Test the behavior when Pro gem is installed but not licensed
    • Test the behavior when Pro gem is installed and licensed
  2. Test Edge Cases

    • What happens if a user has old config in their initializer?
    • What happens during the transition period?

Documentation

  1. Add Migration Error Messages

    If users try to set RSC configs in ReactOnRails.configure, provide helpful error messages:

    def rsc_bundle_js_file=(value)
      raise ReactOnRails::Error, <<~MSG
        rsc_bundle_js_file has been moved to React on Rails Pro.
        Please use ReactOnRailsPro.configure instead.
        See: https://github.com/shakacode/react_on_rails/blob/master/CHANGELOG.md
      MSG
    end
  2. Update View Helpers Documentation

    The docs at docs/api-reference/view-helpers-api.md are well updated, but consider adding a note about what happens if Pro helpers are called without Pro installed.


🔒 Security Considerations

No security concerns identified. The changes don't introduce security vulnerabilities. The enforce_private_server_bundles configuration remains in the open-source gem, which is appropriate.


🎯 Performance Considerations

No performance regressions expected. The additional Pro availability checks are minimal and only executed during initialization or when features are used.


📋 Pre-Merge Checklist

Before merging this PR, ensure:

  • Documentation is complete
  • Migration guide is clear
  • CHANGELOG entries are accurate
  • FIX CRITICAL BUG: ensure_webpack_generated_files_exists method
  • Add tests for removed configurations
  • Add defensive checks for Pro availability
  • Run bundle exec rubocop and fix all violations (per CLAUDE.md)
  • Ensure all files end with newline character (per CLAUDE.md)
  • Run full test suite: rake
  • Test with Pro gem installed
  • Test without Pro gem installed

Summary

This is a well-thought-out refactoring with excellent documentation. The critical bug in ensure_webpack_generated_files_exists must be fixed before merging. Once that's addressed along with the recommended test coverage improvements, this PR will be ready to merge.

Great work on maintaining clean separation between open-source and Pro features! 🎉

@claude
Copy link

claude bot commented Oct 23, 2025

PR Review: Move Pro-specific utilities and configurations to Pro gem

I've reviewed PR #1875 and have the following feedback organized by category:

✅ Code Quality & Architecture

Excellent separation of concerns:

  • Moving RSC configurations (rsc_bundle_js_file, react_client_manifest_file, react_server_client_manifest_file) from ReactOnRails::Configuration to ReactOnRailsPro::Configuration is the right architectural decision
  • Helper methods (stream_react_component, rsc_payload_react_component) properly migrated from open-source to Pro gem
  • Clean delegation pattern: ReactOnRails::Utils.rsc_support_enabled? now delegates to ReactOnRailsPro::Utils.rsc_support_enabled?

Code organization:

  • New Pro utility methods in react_on_rails_pro/lib/react_on_rails_pro/utils.rb are well-structured:
    • rsc_bundle_js_file_path (lines 22-27)
    • react_client_manifest_file_path (lines 29-34)
    • react_server_client_manifest_file_path (lines 38-48)
    • rsc_support_enabled? (lines 50-52)
  • Constants properly moved: DEFAULT_REACT_CLIENT_MANIFEST_FILE and DEFAULT_REACT_SERVER_CLIENT_MANIFEST_FILE removed from open-source configuration

Best practices followed:

  • Proper error handling with descriptive messages
  • Instance variable caching with Rails environment checks (@rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?)
  • Consistent code style following RuboCop conventions

🔒 Security Considerations

License validation:

  • Pro features are properly gated behind license checks (as shown in the existing Pro infrastructure)
  • No security vulnerabilities introduced by this refactoring

Access control:

  • Helper methods appropriately raise errors when Pro gem not available
  • Configuration validation prevents invalid setups

⚠️ Potential Issues & Recommendations

1. Breaking changes are well-documented

  • CHANGELOG.md properly documents migration path with clear before/after examples (lines 76-100)
  • Documentation updated in docs/api-reference/configuration.md and docs/api-reference/view-helpers-api.md

2. Conditional logic requires careful testing:

In lib/react_on_rails/packer_utils.rb (lines 58-62):

# Check Pro RSC bundle if Pro is available
if ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro)
  is_bundle_running_on_server ||= (bundle_name == ReactOnRailsPro.configuration.rsc_bundle_js_file)
end

Recommendation: The defined?(ReactOnRailsPro) check is redundant since react_on_rails_pro? already checks for Pro availability. Consider simplifying:

if ReactOnRails::Utils.react_on_rails_pro?
  is_bundle_running_on_server ||= (bundle_name == ReactOnRailsPro.configuration.rsc_bundle_js_file)
end

3. Test helper compatibility:

In lib/react_on_rails/test_helper/webpack_assets_status_checker.rb (lines 53-64), the logic properly handles Pro manifest files, but consider extracting this into a helper method for clarity:

def resolve_asset_path(bundle_name)
  if ReactOnRails::Utils.react_on_rails_pro?
    pro_config = ReactOnRailsPro.configuration
    return ReactOnRailsPro::Utils.react_client_manifest_file_path if bundle_name == pro_config.react_client_manifest_file
    return ReactOnRailsPro::Utils.react_server_client_manifest_file_path if bundle_name == pro_config.react_server_client_manifest_file
  end
  
  ReactOnRails::Utils.bundle_js_file_path(bundle_name)
end

4. Backward compatibility:

The delegation in lib/react_on_rails/utils.rb:233-241 is good:

def self.rsc_support_enabled?
  return false unless react_on_rails_pro?
  
  ReactOnRailsPro::Utils.rsc_support_enabled?
end

This ensures open-source users don't break when calling this method.

🧪 Test Coverage

Strong test coverage added:

  • New configuration specs in react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb
  • Utility method specs in react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb covering:
    • rsc_bundle_hash calculation
    • Manifest file path resolution
    • Bundle hash generation with/without webpack hashes
  • Tests removed from open-source specs appropriately (e.g., spec/react_on_rails/configuration_spec.rb removed RSC config tests)

Recommendation: Add integration tests to verify:

  1. Error messages when Pro users don't migrate their configuration
  2. Graceful degradation when open-source users call Pro-dependent methods
  3. Dev server detection works correctly with RSC bundles

📊 Performance Considerations

No performance regressions expected:

  • Caching strategy maintained for bundle paths
  • Conditional checks add minimal overhead
  • No new N+1 queries or expensive operations introduced

Positive impacts:

  • Open-source gem becomes slightly lighter (169 lines removed from helper.rb)
  • Clearer code paths reduce cognitive overhead

📝 Documentation

Excellent documentation updates:

  • Migration guide in CHANGELOG.md with clear examples
  • API reference updated to distinguish Pro-only helpers
  • Pro configuration docs reference added to open-source configuration docs
  • View helpers API now has dedicated "Pro-Only View Helpers" section

Minor suggestion: Consider adding a migration checklist to the Pro docs:

## Migrating to 4.0.0+

- [ ] Move `rsc_bundle_js_file` to `ReactOnRailsPro.configure`
- [ ] Move `react_client_manifest_file` to `ReactOnRailsPro.configure`
- [ ] Move `react_server_client_manifest_file` to `ReactOnRailsPro.configure`
- [ ] Run tests to ensure streaming still works
- [ ] Update CI configuration if needed

🎯 Phase Progress

According to the PR description, only Phase 1 & 2 are complete. The remaining phases look sensible. Recommendations for future phases:

Phase 3-7: When moving remaining streaming/RSC methods:

  • Ensure consistent error messages across all Pro-gated features
  • Consider creating a shared concern for Pro feature gating
  • Add deprecation warnings if any methods remain temporarily in open-source

Phase 8 (Doctor Diagnostics):

  • Make sure doctor command gives helpful guidance when RSC features are used without Pro
  • Test the doctor output in both open-source and Pro contexts

Phase 10 (Dummy Apps):

  • Critical to test both dummy apps thoroughly
  • Consider adding automated tests that verify both apps start correctly

⚡ Quick Wins Before Merge

  1. Simplify redundant check in packer_utils.rb:58 (remove defined?(ReactOnRailsPro))
  2. Add trailing newlines - Ensure all files end with newline per CLAUDE.md requirements
  3. Run RuboCop - bundle exec rubocop must pass before merge (per CLAUDE.md)
  4. Extract helper method in webpack_assets_status_checker.rb for better readability

🎉 Summary

This is a well-executed refactoring that properly separates Pro features from open-source code. The migration path is clear, documentation is comprehensive, and test coverage is solid.

Status: ✅ Approved with minor suggestions

Risk Level: Low - Changes are well-isolated and properly tested

Recommendation: Address the minor code quality suggestions above, complete remaining phases incrementally, and ensure all linting passes before final merge.

Great work on maintaining backward compatibility while achieving clean separation! 🚀


Note: Remember to run the following before merging each phase:

bundle exec rubocop
rake

@AbanoubGhadban AbanoubGhadban changed the title [WIP] Move Pro-specific utilities and configurations to Pro gem Move Pro-specific utilities and configurations to Pro gem Oct 23, 2025
@AbanoubGhadban AbanoubGhadban marked this pull request as ready for review October 23, 2025 17:11
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
lib/react_on_rails/configuration.rb (1)

313-323: Critical: NoMethodError when calling removed RSC configuration methods.

The ensure_webpack_generated_files_exists method references rsc_bundle_js_file, react_client_manifest_file, and react_server_client_manifest_file (lines 319-322), but these attributes were removed from the Configuration class (line 70-72). This will raise a NoMethodError when this method is called during configuration setup.

Since these are now Pro-only features, you need to conditionally check for their presence. Consider this fix:

   def ensure_webpack_generated_files_exists
     return unless webpack_generated_files.empty?

     self.webpack_generated_files = [
       "manifest.json",
       server_bundle_js_file,
-      rsc_bundle_js_file,
-      react_client_manifest_file,
-      react_server_client_manifest_file
+      (ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro) ? ReactOnRailsPro.configuration.rsc_bundle_js_file : nil),
+      (ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro) ? ReactOnRailsPro.configuration.react_client_manifest_file : nil),
+      (ReactOnRails::Utils.react_on_rails_pro? && defined?(ReactOnRailsPro) ? ReactOnRailsPro.configuration.react_server_client_manifest_file : nil)
     ].compact_blank
   end
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)

120-129: Update error message to reference the actual minimum version instead of retracted 15.0.0

The error message references react_on_rails version "15.0.0 or higher", but that version was retracted. Version 15.0.0 has been retracted, and users should upgrade directly to v16.0.0. Update the message to say "16.0.0 or higher" to reflect the current minimum released version with RSC support.

🧹 Nitpick comments (15)
react_on_rails_pro/spec/react_on_rails_pro/spec_helper.rb (1)

46-46: Consider making test logging conditional for cleaner output.

While logging to stdout is helpful for debugging, it can make test output verbose. Consider making this conditional based on an environment variable to keep output clean by default:

Rails.logger = Logger.new(ENV['VERBOSE_TESTS'] ? $stdout : IO::NULL)

Or adjust the log level to only show warnings and errors:

Rails.logger = Logger.new($stdout)
Rails.logger.level = ENV['VERBOSE_TESTS'] ? Logger::DEBUG : Logger::WARN

This allows developers to opt into verbose logging when needed without cluttering the default test output.

react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb (1)

66-76: Nice code cleanup.

Introducing the local config variable improves readability without changing functionality. This is a good refactoring practice.

lib/react_on_rails/test_helper/webpack_assets_status_checker.rb (1)

53-62: Ensure returned paths are filesystem paths for stale checks

stale_generated_files calls File.exist?/File.mtime on these values. ReactOnRailsPro::Utils.react_client_manifest_file_path can return a dev-server URL, which will cause false “stale” results. Prefer always returning a filesystem path here.

Suggested change:

  • Resolve both Pro manifest names via ReactOnRails::Utils.bundle_js_file_path to guarantee a local path (manifest lookup → file path fallback), or guard against URLs before returning.

Example diff:

-              if bundle_name == pro_config.react_client_manifest_file
-                ReactOnRailsPro::Utils.react_client_manifest_file_path
-              elsif bundle_name == pro_config.react_server_client_manifest_file
-                ReactOnRailsPro::Utils.react_server_client_manifest_file_path
+              if bundle_name == pro_config.react_client_manifest_file
+                ReactOnRails::Utils.bundle_js_file_path(bundle_name)
+              elsif bundle_name == pro_config.react_server_client_manifest_file
+                ReactOnRails::Utils.bundle_js_file_path(bundle_name)

Can you confirm whether asset_uri_from_packer ever returns an http(s) URL for the client manifest in your test env? If yes, the above change (or equivalent URL-to-path handling) is required for correct staleness detection.

docs/api-reference/view-helpers-api.md (1)

120-159: Pro-only helpers section looks correct; minor copy nit

Consider tightening “Used in conjunction with RSC support” → “Used with RSC support” for brevity.

spec/react_on_rails/utils_spec.rb (1)

247-267: Good isolation of Pro behavior in OSS spec

The local ReactOnRailsPro stub plus forcing react_on_rails_pro?=true keeps tests hermetic. Optionally, also stub ReactOnRailsPro::Utils if future code paths consult it.

spec/dummy/spec/packs_generator_spec.rb (2)

237-244: Simplify and harden the Utils stub (avoid double‑stubbing and Class override).

Use a Module stub and a single allow; reduces risk of constant shape mismatches and duplicate stubs.

-        stub_const("ReactOnRailsPro::Utils", Class.new do
-          def self.rsc_support_enabled?
-            true
-          end
-        end)
-        allow(ReactOnRailsPro::Utils).to receive_messages(
-          rsc_support_enabled?: true
-        )
+        stub_const("ReactOnRailsPro::Utils", Module.new)
+        allow(ReactOnRailsPro::Utils).to receive(:rsc_support_enabled?).and_return(true)

315-319: Clarify context nesting.

“when RSC support is disabled” is nested under “when RSC support is enabled”, which is confusing. Consider renaming the outer context to “when ReactOnRails Pro is available” and toggle RSC per inner contexts, or lift the disabled case to a sibling context.

react_on_rails_pro/docs/configuration.md (1)

125-164: Add a short note on path resolution and dev‑server behavior for RSC files.

Clarify that the server‑side manifest isn’t served by the dev server and where each path is resolved from.

   ################################################################################
   # REACT SERVER COMPONENTS (RSC) CONFIGURATION
   ################################################################################
 
+  # Note:
+  # - config.rsc_bundle_js_file and config.react_server_client_manifest_file are treated as
+  #   server bundles/outputs and are resolved from private (non‑public) output paths first.
+  #   They are not served by the dev server.
+  # - config.react_client_manifest_file may resolve to an HTTP URL when the dev server is running.
+  # - If migrating from OSS, move any prior RSC settings to this Pro initializer.
react_on_rails_pro/lib/react_on_rails_pro/utils.rb (1)

22-52: Avoid memoization in test to reduce flakiness.

Align cache guards with other helpers by bypassing cache in both development and test.

-      return @rsc_bundle_path if @rsc_bundle_path && !Rails.env.development?
+      return @rsc_bundle_path if @rsc_bundle_path && !(Rails.env.development? || Rails.env.test?)
@@
-      return @react_client_manifest_path if @react_client_manifest_path && !Rails.env.development?
+      return @react_client_manifest_path if @react_client_manifest_path && !(Rails.env.development? || Rails.env.test?)
@@
-      return @react_server_manifest_path if @react_server_manifest_path && !Rails.env.development?
+      return @react_server_manifest_path if @react_server_manifest_path && !(Rails.env.development? || Rails.env.test?)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)

110-118: Validate required RSC paths when RSC is enabled.

Fail fast if any RSC path is blank to avoid late resolution errors.

 def setup_config_values
   configure_default_url_if_not_provided
   validate_url
   validate_remote_bundle_cache_adapter
   setup_renderer_password
   setup_assets_to_copy
   setup_execjs_profiler_if_needed
   check_react_on_rails_support_for_rsc
+  validate_rsc_required_paths
 end
@@
+    def validate_rsc_required_paths
+      return unless enable_rsc_support
+
+      %i[rsc_bundle_js_file react_client_manifest_file react_server_client_manifest_file].each do |attr|
+        value = public_send(attr)
+        if value.blank?
+          raise ReactOnRailsPro::Error, "config.#{attr} must be set when enable_rsc_support is true"
+        end
+      end
+    end

Also applies to: 125-129

react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb (3)

251-296: Rails.env stubbing: prefer replacing the inquirer over stubbing predicate.

allow(Rails.env).to receive(:development?) works but is brittle. Safer and RuboCop‑friendly: return a fresh StringInquirer and avoid predicate stubs.

Example:

-        allow(Rails.env).to receive(:development?).and_return(false)
+        allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("production"))

And for the dev case:

-        allow(Rails.env).to receive(:development?).and_return(true)
+        allow(Rails).to receive(:env).and_return(ActiveSupport::StringInquirer.new("development"))

309-348: Avoid receive_message_chain; stub dev_server explicitly.

receive_message_chain("dev_server.running?") is discouraged by rubocop‑rspec and is brittle. Stub dev_server to a double with running?:

-          before do
-            allow(::Shakapacker).to receive_message_chain("dev_server.running?")
-              .and_return(false)
-          end
+          before do
+            dev_server = instance_double(::Shakapacker::DevServer, running?: false)
+            allow(::Shakapacker).to receive(:dev_server).and_return(dev_server)
+          end

Similarly, where you use manifest.lookup!, prefer stubbing manifest to a double responding to lookup! to avoid message chains.


464-475: Clarify “singular day” wording.

Test description says “singular day” but expectation keeps “day(s)”. Either change description or (optionally) pluralize in implementation/expectation.

Example description tweak:

-        it "returns attribution comment with singular day" do
+        it "returns attribution comment with day count wording" do
react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb (2)

184-191: Docs/code mismatch: helper does not raise if RSC disabled.

Comment says “raises if RSC support is not enabled,” but the method doesn’t check. Per learnings, validation happens elsewhere (pack generation/registration), so the helper should not add another check. Update the comment to reflect that failure occurs upstream, not here.

Based on learnings

-  # @raise [ReactOnRailsPro::Error] if RSC support is not enabled in configuration
+  # Note: If RSC is disabled, an error will arise during pack generation or registration, not here.

257-273: Cache write‑through buffers every chunk; consider bounding.

buffered_chunks grows with stream length; for very chatty streams this can grow large before Rails.cache.write. Consider:

  • Cap number of buffered chunks or
  • Stream to a temp file and read back for write, or
  • Enforce an :expires_in default for cache_options.
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 64dc33a and 198eb0b.

📒 Files selected for processing (25)
  • .gitignore (1 hunks)
  • CHANGELOG.md (1 hunks)
  • docs/api-reference/configuration.md (1 hunks)
  • docs/api-reference/view-helpers-api.md (1 hunks)
  • lib/react_on_rails/configuration.rb (1 hunks)
  • lib/react_on_rails/helper.rb (0 hunks)
  • lib/react_on_rails/packer_utils.rb (1 hunks)
  • lib/react_on_rails/test_helper/webpack_assets_status_checker.rb (1 hunks)
  • lib/react_on_rails/utils.rb (2 hunks)
  • react_on_rails_pro/CHANGELOG.md (1 hunks)
  • react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb (3 hunks)
  • react_on_rails_pro/docs/configuration.md (1 hunks)
  • react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (5 hunks)
  • react_on_rails_pro/lib/react_on_rails_pro/request.rb (3 hunks)
  • react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb (1 hunks)
  • react_on_rails_pro/lib/react_on_rails_pro/utils.rb (3 hunks)
  • react_on_rails_pro/spec/dummy/config/initializers/react_on_rails.rb (0 hunks)
  • react_on_rails_pro/spec/dummy/config/initializers/react_on_rails_pro.rb (1 hunks)
  • react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb (1 hunks)
  • react_on_rails_pro/spec/react_on_rails_pro/request_spec.rb (1 hunks)
  • react_on_rails_pro/spec/react_on_rails_pro/spec_helper.rb (1 hunks)
  • react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb (3 hunks)
  • spec/dummy/spec/packs_generator_spec.rb (2 hunks)
  • spec/react_on_rails/configuration_spec.rb (0 hunks)
  • spec/react_on_rails/utils_spec.rb (2 hunks)
💤 Files with no reviewable changes (3)
  • react_on_rails_pro/spec/dummy/config/initializers/react_on_rails.rb
  • lib/react_on_rails/helper.rb
  • spec/react_on_rails/configuration_spec.rb
🧰 Additional context used
📓 Path-based instructions (2)
{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}

📄 CodeRabbit inference engine (CLAUDE.md)

{Gemfile,Rakefile,config.ru,**/*.{rb,rake,gemspec,ru}}: All Ruby code must pass RuboCop with zero offenses before commit/push
RuboCop is the sole authority for Ruby file formatting; never manually format Ruby files

Files:

  • react_on_rails_pro/spec/react_on_rails_pro/spec_helper.rb
  • react_on_rails_pro/lib/react_on_rails_pro/request.rb
  • spec/dummy/spec/packs_generator_spec.rb
  • lib/react_on_rails/utils.rb
  • spec/react_on_rails/utils_spec.rb
  • react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb
  • react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb
  • react_on_rails_pro/lib/react_on_rails_pro/utils.rb
  • react_on_rails_pro/spec/react_on_rails_pro/request_spec.rb
  • lib/react_on_rails/test_helper/webpack_assets_status_checker.rb
  • react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb
  • react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb
  • lib/react_on_rails/configuration.rb
  • lib/react_on_rails/packer_utils.rb
  • react_on_rails_pro/spec/dummy/config/initializers/react_on_rails_pro.rb
  • react_on_rails_pro/lib/react_on_rails_pro/configuration.rb
**/*.{js,jsx,ts,tsx,css,scss,json,yml,yaml,md}

📄 CodeRabbit inference engine (CLAUDE.md)

Prettier is the sole authority for formatting all non-Ruby files; never manually format them

Files:

  • react_on_rails_pro/CHANGELOG.md
  • react_on_rails_pro/docs/configuration.md
  • docs/api-reference/view-helpers-api.md
  • CHANGELOG.md
  • docs/api-reference/configuration.md
🧠 Learnings (7)
📓 Common learnings
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.
📚 Learning: 2025-04-26T21:55:55.874Z
Learnt from: alexeyr-ci2
PR: shakacode/react_on_rails#1732
File: spec/dummy/client/app-react16/startup/ReduxSharedStoreApp.client.jsx:40-44
Timestamp: 2025-04-26T21:55:55.874Z
Learning: In the react_on_rails project, files under `app-react16` directories are copied/moved to corresponding `/app` directories during the conversion process (removing the `-react16` suffix), which affects their relative import paths at runtime.

Applied to files:

  • react_on_rails_pro/lib/react_on_rails_pro/request.rb
  • react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb
📚 Learning: 2025-07-08T05:57:29.630Z
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1745
File: node_package/src/RSCRequestTracker.ts:8-14
Timestamp: 2025-07-08T05:57:29.630Z
Learning: The global `generateRSCPayload` function in React on Rails Pro (RORP) is provided by the framework during rendering requests, not implemented in application code. The `declare global` statements are used to document the expected interface that RORP will inject at runtime.

Applied to files:

  • react_on_rails_pro/lib/react_on_rails_pro/request.rb
  • react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation in React on Rails Pro is handled through a chain of validations:
1. Pro version check in `run_stream_inside_fiber`
2. RSC support check during pack generation via `ReactOnRailsPro.configuration.enable_rsc_support`
3. RSC support validation during component registration
This makes additional validation in the helper methods unnecessary.

Applied to files:

  • react_on_rails_pro/lib/react_on_rails_pro/request.rb
  • spec/dummy/spec/packs_generator_spec.rb
  • react_on_rails_pro/CHANGELOG.md
  • react_on_rails_pro/docs/configuration.md
  • lib/react_on_rails/utils.rb
  • spec/react_on_rails/utils_spec.rb
  • react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb
  • react_on_rails_pro/lib/react_on_rails_pro/utils.rb
  • lib/react_on_rails/test_helper/webpack_assets_status_checker.rb
  • react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb
  • docs/api-reference/view-helpers-api.md
  • CHANGELOG.md
  • react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb
  • docs/api-reference/configuration.md
  • lib/react_on_rails/packer_utils.rb
  • react_on_rails_pro/spec/dummy/config/initializers/react_on_rails_pro.rb
📚 Learning: 2025-02-18T13:08:01.477Z
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1644
File: lib/react_on_rails/helper.rb:190-197
Timestamp: 2025-02-18T13:08:01.477Z
Learning: RSC support validation is handled in deeper level calls of the React on Rails Pro codebase, so it doesn't need to be validated again in the `rsc_payload_react_component` helper method.

Applied to files:

  • react_on_rails_pro/lib/react_on_rails_pro/request.rb
  • spec/dummy/spec/packs_generator_spec.rb
  • lib/react_on_rails/utils.rb
  • react_on_rails_pro/lib/react_on_rails_pro/utils.rb
  • docs/api-reference/view-helpers-api.md
📚 Learning: 2025-09-15T21:24:48.207Z
Learnt from: AbanoubGhadban
PR: shakacode/react_on_rails#1781
File: node_package/src/ClientSideRenderer.ts:82-95
Timestamp: 2025-09-15T21:24:48.207Z
Learning: In React on Rails, the force_load feature includes both explicit `data-force-load="true"` usage and the ability to hydrate components during the page loading state (`document.readyState === 'loading'`). Both capabilities require a Pro license, so the condition `!railsContext.rorPro && (isComponentForceLoaded || document.readyState === 'loading')` correctly gates both scenarios.

Applied to files:

  • react_on_rails_pro/CHANGELOG.md
  • react_on_rails_pro/lib/react_on_rails_pro/utils.rb
  • docs/api-reference/view-helpers-api.md
📚 Learning: 2025-09-16T08:01:11.146Z
Learnt from: justin808
PR: shakacode/react_on_rails#1770
File: lib/generators/react_on_rails/templates/base/base/app/javascript/src/HelloWorld/ror_components/HelloWorld.client.jsx:2-2
Timestamp: 2025-09-16T08:01:11.146Z
Learning: React on Rails uses webpack CSS Modules configuration with namedExports: true, which requires the import syntax `import * as style from './file.module.css'` rather than the default export pattern. This configuration enables better tree shaking and bundle size optimization for CSS modules.

Applied to files:

  • react_on_rails_pro/docs/configuration.md
  • react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb
  • lib/react_on_rails/test_helper/webpack_assets_status_checker.rb
  • docs/api-reference/configuration.md
🧬 Code graph analysis (13)
react_on_rails_pro/lib/react_on_rails_pro/request.rb (1)
react_on_rails_pro/lib/react_on_rails_pro/utils.rb (3)
  • rsc_bundle_js_file_path (22-27)
  • react_client_manifest_file_path (29-34)
  • react_server_client_manifest_file_path (38-48)
spec/dummy/spec/packs_generator_spec.rb (1)
lib/react_on_rails/utils.rb (1)
  • rsc_support_enabled? (238-242)
lib/react_on_rails/utils.rb (3)
lib/react_on_rails/configuration.rb (1)
  • configuration (14-57)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
react_on_rails_pro/lib/react_on_rails_pro/utils.rb (1)
  • rsc_support_enabled? (50-52)
spec/react_on_rails/utils_spec.rb (1)
lib/react_on_rails/configuration.rb (1)
  • configuration (14-57)
react_on_rails_pro/lib/react_on_rails_pro/server_rendering_js_code.rb (1)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb (2)
lib/react_on_rails/helper.rb (5)
  • internal_react_component (480-503)
  • create_render_options (363-371)
  • server_rendered_react_component (535-594)
  • build_react_component_result_for_server_rendered_string (377-402)
  • compose_react_component_html_with_spec_and_console (438-445)
lib/react_on_rails/react_component/render_options.rb (1)
  • replay_console (86-88)
react_on_rails_pro/lib/react_on_rails_pro/utils.rb (3)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
lib/react_on_rails/utils.rb (2)
  • bundle_js_file_path (74-86)
  • rsc_support_enabled? (238-242)
lib/react_on_rails/packer_utils.rb (1)
  • asset_uri_from_packer (80-86)
react_on_rails_pro/spec/react_on_rails_pro/request_spec.rb (2)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
react_on_rails_pro/lib/react_on_rails_pro/server_rendering_pool/node_rendering_pool.rb (2)
  • renderer_bundle_file_name (32-34)
  • rsc_renderer_bundle_file_name (36-38)
lib/react_on_rails/test_helper/webpack_assets_status_checker.rb (4)
lib/react_on_rails/utils.rb (2)
  • react_on_rails_pro? (215-223)
  • bundle_js_file_path (74-86)
lib/react_on_rails/configuration.rb (1)
  • configuration (14-57)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
react_on_rails_pro/lib/react_on_rails_pro/utils.rb (2)
  • react_client_manifest_file_path (29-34)
  • react_server_client_manifest_file_path (38-48)
react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb (3)
react_on_rails_pro/lib/react_on_rails_pro/utils.rb (4)
  • rsc_bundle_js_file_path (22-27)
  • rsc_support_enabled? (50-52)
  • react_client_manifest_file_path (29-34)
  • react_server_client_manifest_file_path (38-48)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
lib/react_on_rails/utils.rb (1)
  • rsc_support_enabled? (238-242)
react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb (1)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (2)
  • configure (4-7)
  • configuration (9-37)
lib/react_on_rails/packer_utils.rb (3)
lib/react_on_rails/configuration.rb (1)
  • configuration (14-57)
react_on_rails_pro/lib/react_on_rails_pro/configuration.rb (1)
  • configuration (9-37)
lib/react_on_rails/utils.rb (1)
  • react_on_rails_pro? (215-223)
react_on_rails_pro/spec/dummy/config/initializers/react_on_rails_pro.rb (1)
react_on_rails_pro/spec/dummy/client/node-renderer.js (1)
  • config (30-66)
🪛 LanguageTool
docs/api-reference/view-helpers-api.md

[style] ~151-~151: ‘in conjunction with’ might be wordy. Consider a shorter alternative.
Context: ...ormat for client-side consumption. Used in conjunction with RSC support to enable: - Reduced JavaS...

(EN_WORDINESS_PREMIUM_IN_CONJUNCTION_WITH)

🔇 Additional comments (17)
.gitignore (1)

78-78: Clarify the purpose of the .fuse_hidden* pattern addition.

This change adds a gitignore pattern for FUSE temporary files, which appears unrelated to the PR's objectives of moving Pro-specific utilities and configurations.

Verify whether:

  • This pattern is necessary for the PRs functionality, or
  • This is an accidental commit of developer environment configuration that should be removed or moved to a personal .git/info/exclude file instead.
react_on_rails_pro/lib/react_on_rails_pro/request.rb (1)

52-52: LGTM! Namespace migration is correct.

The changes correctly migrate RSC-related path resolution from ReactOnRails::Utils to ReactOnRailsPro::Utils, aligning with the broader migration of RSC functionality to the Pro gem.

Also applies to: 157-157, 181-182

lib/react_on_rails/packer_utils.rb (1)

58-63: LGTM! Conditional Pro support is well implemented.

The refactored logic correctly adds conditional RSC bundle support when Pro is available, while maintaining backward compatibility for open-source users. The defensive checks (react_on_rails_pro? and defined?(ReactOnRailsPro)) ensure no errors occur in non-Pro environments.

docs/api-reference/configuration.md (1)

107-122: LGTM! Documentation correctly reflects RSC migration to Pro.

The documentation update appropriately redirects users to the Pro documentation for RSC-related configuration, maintaining clear boundaries between open-source and Pro features.

CHANGELOG.md (1)

76-108: LGTM! Clear migration documentation.

The CHANGELOG entry provides excellent migration guidance with before/after code examples and links to Pro documentation. This will help users upgrade smoothly.

react_on_rails_pro/spec/dummy/config/initializers/react_on_rails_pro.rb (1)

10-11: LGTM! Demonstrates correct Pro configuration pattern.

This example correctly shows how to configure the RSC bundle in the Pro initializer, providing a good reference for users migrating their configuration.

react_on_rails_pro/spec/react_on_rails_pro/request_spec.rb (1)

23-24: LGTM! Test consolidation and Pro namespace migration.

The changes improve test readability by consolidating multiple stub calls into single receive_messages calls, and correctly update to use ReactOnRailsPro::Utils for RSC bundle path resolution.

Also applies to: 32-34, 37-37

react_on_rails_pro/CHANGELOG.md (1)

22-33: Docs read well; migration scoped and clear

The relocation of RSC configs and streaming helpers to Pro is explained succinctly with a migration pointer. LGTM.

Also applies to: 36-36

spec/react_on_rails/utils_spec.rb (1)

659-659: Test relocation note is helpful

Acknowledging the move of RSC utils tests to Pro keeps the OSS suite lean. LGTM.

react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb (1)

202-260: RSC configuration tests are correct and well-aligned with constants

The DEFAULT_* constants in configuration.rb (lines 59-61) match exactly with the test expectations:

  • "rsc-bundle.js" ✓
  • "react-client-manifest.json" ✓
  • "react-server-client-manifest.json" ✓

Tests comprehensively cover defaults, explicit assignments, nil values, and combined setup. No brittle expectations.

lib/react_on_rails/utils.rb (1)

236-242: Delegating RSC support detection to Pro looks good.

react_on_rails_pro/spec/react_on_rails_pro/utils_spec.rb (2)

229-249: LGTM: rsc_support_enabled? mirrors configuration state.

Clean, direct mapping to ReactOnRailsPro.configuration.enable_rsc_support.


392-401: LGTM: manifest path resolution, caching behavior, and nil‑guard error.

  • Correct delegation to ReactOnRails::Utils.bundle_js_file_path.
  • Caching toggled by Rails.env.development? is covered.
  • Error case when filename is nil is asserted.

Also applies to: 402-425, 427-437

react_on_rails_pro/app/helpers/react_on_rails_pro_helper.rb (4)

126-134: Default immediate_hydration: confirm client-side Pro gating remains.

Setting immediate_hydration: true by default is fine as long as the client still gates hydration behind Pro (via railsContext.rorPro and related checks).

Based on learnings: force-load/hydration gating is enforced client-side for Pro. Please confirm the client path still checks railsContext.rorPro for immediate hydration.


294-313: Fiber wrapper error path and gating note.

Good: clear error if stream_view_containing_react_components was not invoked. If license/Pro gating used to live here, ensure it’s intentionally moved upstream so this method focuses solely on fiber plumbing.

Confirm that license/Pro checks and diagnostics are handled earlier in the flow (e.g., when starting the streaming view or in the server renderer), per the migration plan.


325-332: NDJSON chunking looks correct.

Transforming stream chunks to JSON + "\n" for RSC payloads is straightforward and safe for streaming.


334-358: HTML streaming composition is sound; console replay gated.

  • First chunk composes full markup/spec tag; subsequent chunks append HTML and optional console script.
  • Uses existing helpers, preserves replay_console semantics.


---

### cached_react_component and cached_react_component_hash
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to Pro-Only View Helpers section added below

@claude
Copy link

claude bot commented Oct 23, 2025

Pull Request Review: Move Pro-specific utilities and configurations to Pro gem

Overall Assessment

This is a well-structured refactoring that effectively separates Pro-specific features from the open-source codebase. The PR demonstrates good architectural planning with clear phases and comprehensive documentation. The code quality is high, and the migration path is well-documented.

Recommendation: Approve with minor suggestions


Strengths

1. Excellent Architecture & Separation of Concerns

  • Clean separation of RSC configurations from open-source to Pro gem
  • Pro configurations properly moved to ReactOnRailsPro::Configuration
  • View helpers correctly relocated to Pro helper module
  • Utility methods properly delegated from open-source to Pro

2. Strong Documentation & Migration Guidance

  • Comprehensive CHANGELOG with clear Before/After migration examples
  • Updated API documentation clearly marking Pro-only features
  • Pro documentation links provided for users
  • Phase-based implementation plan is well-organized

3. Backward Compatibility & Safety

  • Proper Pro gem detection using ReactOnRails::Utils.react_on_rails_pro? checks
  • Graceful fallbacks when Pro gem is not available
  • No breaking changes for open-source-only users
  • Configuration validation in Pro gem

4. Code Quality

  • Consistent error handling with clear error messages
  • Good use of memoization for file path resolution
  • Proper handling of development vs production environments

Issues & Suggestions

Critical Issues

None identified. The PR is safe to merge.

Moderate Suggestions

  1. Test Coverage Gap - Consider adding integration tests for migration scenarios and error cases in resolve_asset_path method.

  2. Path Resolution Logic (lib/react_on_rails/packer_utils.rb:58-62) - Consider extracting to a helper method for better testability.

  3. Defensive Coding (lib/react_on_rails/utils.rb:239-241) - Consider adding respond_to? check before calling ReactOnRailsPro::Utils.rsc_support_enabled?

Minor Suggestions

  1. Documentation Clarity - Make breaking change warning more explicit in docs/api-reference/configuration.md

  2. Error Messages - Could include component names and documentation links for easier debugging

  3. .gitignore Entry - The .claude/.fuse_hidden* entry seems unrelated to PR purpose


Security & Performance

Security: No concerns. Server bundle detection properly handles Pro paths.

Performance: Good characteristics with proper memoization and caching.


Testing Recommendations

Before merging complete PR series:

  1. Integration tests for both gems
  2. Upgrade path tests (v16.1 to v16.2)
  3. Error message tests
  4. Documentation validation
  5. Backward compatibility verification

Compliance with CLAUDE.md

Adheres to repository guidelines. Before merging: run bundle exec rubocop and fix all violations.


Conclusion

Excellent refactoring work. The migration path is clear, documentation is comprehensive, and code quality is high. Suggestions above are minor improvements that enhance robustness but don't block merging Phase 2.

Next Steps:

  1. Address moderate suggestions (especially test coverage)
  2. Run full test suite
  3. Run bundle exec rubocop and fix violations
  4. Merge Phase 2
  5. Continue with remaining phases

Great work!

Reviewed by: Claude Code
Review Date: 2025-10-23

@claude
Copy link

claude bot commented Oct 23, 2025

Code Review: PR #1875 - Move Pro-specific utilities and configurations to Pro gem

I've completed a comprehensive review of this PR. Overall, this is excellent architectural work that significantly improves code separation and maintainability.

✅ Strengths

1. Excellent Architectural Separation

  • Clear boundary between open-source and Pro features
  • Proper delegation pattern (e.g., ReactOnRails::Utils.rsc_support_enabled? → ReactOnRailsPro::Utils.rsc_support_enabled?)
  • Well-organized code structure

2. Comprehensive Documentation

  • CHANGELOG entries provide clear migration paths
  • Documentation properly reflects Pro-only features
  • PR description is thorough with detailed phase checklist

3. Strong Test Coverage

  • New RSC configuration tests (configuration_spec.rb:202-260)
  • Utility method tests migrated properly
  • Tests verify defaults, custom values, and nil values

4. Backward Compatibility

  • Graceful fallback when Pro gem unavailable
  • Proper Pro detection before accessing Pro configs
  • No breaking changes for open-source users

⚠️ Issues & Recommendations

1. Caching Invalidation Issue (Medium Priority)

Location: react_on_rails_pro/lib/react_on_rails_pro/utils.rb:22-48
Issue: Cached bundle paths don't reset when switching environments
Recommendation: Follow same pattern as server_bundle_js_file_path

2. Missing Nil Check (Low Priority)

Location: react_on_rails_pro/lib/react_on_rails_pro/utils.rb:50-52
Recommendation: Add nil safety to rsc_support_enabled?

3. Missing Configuration Validation (Medium Priority)

Location: lib/react_on_rails/packer_utils.rb:61-63
Issue: No presence check before comparing rsc_bundle_js_file
Recommendation: Add presence check to prevent unexpected behavior

4. Code Duplication (Low Priority)

Location: react_on_rails_pro/lib/react_on_rails_pro/utils.rb:22-48
Recommendation: Extract shared caching pattern to helper method

🔒 Security: No Major Issues ✅

  • Maintains existing security configurations
  • Pro license validation is appropriate
  • Follows secure coding practices

🧪 Test Coverage: Good ✅

Well-tested with suggested additions for edge cases and integration tests

🎯 Performance: No Regressions ✅

  • Caching strategies maintained
  • Pro detection uses memoization
  • Bundle path resolution remains efficient

📊 Summary Ratings

  • Architecture: ⭐⭐⭐⭐⭐ Excellent
  • Code Quality: ⭐⭐⭐⭐☆ Very good
  • Testing: ⭐⭐⭐⭐☆ Good coverage
  • Documentation: ⭐⭐⭐⭐⭐ Comprehensive
  • Security: ⭐⭐⭐⭐⭐ No concerns
  • Performance: ⭐⭐⭐⭐⭐ No regressions

✅ Verdict: Ready to Merge

The core implementation is solid, well-tested, and properly documented. Suggested improvements can be addressed before merge or in follow-up PR. Issues identified are minor and don't block the migration.

Great work on this complex refactoring! 🎉

@AbanoubGhadban AbanoubGhadban merged commit d527ddf into master Oct 23, 2025
22 of 23 checks passed
@AbanoubGhadban AbanoubGhadban deleted the move-pro-utils-and-configs-to-pro-gem branch October 23, 2025 17:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Move RSC and streaming utilities and configs from React on Rails to React on Rails Pro

1 participant