Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Gemfile.development_dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ group :development, :test do
gem "pry-doc"
gem "pry-rails"
gem "pry-rescue"
gem "rbs", require: false
gem "rubocop", "1.61.0", require: false
gem "rubocop-performance", "~>1.20.0", require: false
gem "rubocop-rspec", "~>2.26", require: false
Expand Down
3 changes: 3 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ GEM
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rbs (3.9.5)
logger
rdoc (6.15.1)
erb
psych (>= 4.0.0)
Expand Down Expand Up @@ -437,6 +439,7 @@ DEPENDENCIES
pry-rescue
puma (~> 6.0)
rails (~> 7.1)
rbs
react_on_rails!
rspec-rails
rspec-retry
Expand Down
32 changes: 32 additions & 0 deletions rakelib/rbs.rake
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# frozen_string_literal: true

namespace :rbs do
desc "Validate RBS type signatures"
task :validate do
require "rbs"
require "rbs/cli"

puts "Validating RBS type signatures..."

# Run RBS validate
result = system("bundle exec rbs -I sig validate")

if result
puts "✓ RBS validation passed"
else
puts "✗ RBS validation failed"
exit 1
end
end

desc "Check RBS type signatures (alias for validate)"
task check: :validate

desc "List all RBS files"
task :list do
sig_files = Dir.glob("sig/**/*.rbs")
puts "RBS type signature files:"
sig_files.each { |f| puts " #{f}" }
puts "\nTotal: #{sig_files.count} files"
end
end
52 changes: 52 additions & 0 deletions sig/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# RBS Type Signatures

This directory contains RBS (Ruby Signature) type definitions for the React on Rails gem.

## What is RBS?

RBS is Ruby's official type signature language. It provides type information for Ruby code, enabling:

- Better IDE support and autocomplete
- Static type checking with tools like Steep
- Improved documentation
- Early detection of type-related bugs

## Structure

The signatures are organized to mirror the `lib/` directory structure:

- `react_on_rails.rbs` - Main module and core classes
- `react_on_rails/configuration.rbs` - Configuration class types
- `react_on_rails/helper.rbs` - View helper method signatures
- `react_on_rails/server_rendering_pool.rbs` - Server rendering types
- `react_on_rails/utils.rbs` - Utility method signatures
- And more...

## Validation

To validate the RBS signatures:

```bash
bundle exec rake rbs:validate
```

Or directly:

```bash
bundle exec rbs -I sig validate
```

To list all RBS files:

```bash
bundle exec rake rbs:list
```

## Development

When adding new public methods or classes to the gem, please also add corresponding RBS signatures.

For more information about RBS:

- [RBS Documentation](https://github.com/ruby/rbs)
- [RBS Syntax Guide](https://github.com/ruby/rbs/blob/master/docs/syntax.md)
36 changes: 36 additions & 0 deletions sig/react_on_rails.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Type signatures for ReactOnRails gem

module ReactOnRails
VERSION: String

DEFAULT_GENERATED_ASSETS_DIR: String
DEFAULT_COMPONENT_REGISTRY_TIMEOUT: Integer

def self.configure: () { (Configuration) -> void } -> void
def self.configuration: () -> Configuration

class Error < StandardError
end

class PrerenderError < Error
attr_accessor js_code: String?
attr_accessor err: Hash[Symbol, untyped]
attr_accessor js_message: String

def initialize: (
?component_name: String?,
?js_code: String?,
?err: Hash[Symbol, untyped],
?props: (Hash[Symbol, untyped] | String)?,
?js_message: String
) -> void

def console_messages: () -> Array[String]
def base_message: () -> String
def build_message: () -> String
end

class JsonParseError < Error
def initialize: (Hash[Symbol, untyped] err) -> void
end
end
93 changes: 93 additions & 0 deletions sig/react_on_rails/configuration.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
module ReactOnRails
class Configuration
attr_accessor node_modules_location: String?
attr_accessor server_bundle_js_file: String
attr_accessor prerender: bool
attr_accessor replay_console: bool
attr_accessor trace: bool
attr_accessor development_mode: bool
attr_accessor logging_on_server: bool
attr_accessor server_renderer_pool_size: Integer
attr_accessor server_renderer_timeout: Integer
attr_accessor skip_display_none: bool?
attr_accessor raise_on_prerender_error: bool
attr_accessor generated_assets_dirs: Array[String]?
attr_accessor generated_assets_dir: String
attr_accessor components_subdirectory: String?
attr_accessor webpack_generated_files: Array[String]
attr_accessor rendering_extension: String?
attr_accessor build_test_command: String
attr_accessor build_production_command: String
attr_accessor i18n_dir: String?
attr_accessor i18n_yml_dir: String?
attr_accessor i18n_output_format: Symbol?
attr_accessor i18n_yml_safe_load_options: Hash[Symbol, untyped]?
attr_accessor defer_generated_component_packs: bool
attr_accessor server_render_method: String?
attr_accessor random_dom_id: bool
attr_accessor auto_load_bundle: bool
attr_accessor same_bundle_for_client_and_server: bool
attr_accessor rendering_props_extension: String?
attr_accessor make_generated_server_bundle_the_entrypoint: bool
attr_accessor generated_component_packs_loading_strategy: Symbol?
attr_accessor immediate_hydration: bool
attr_accessor component_registry_timeout: Integer
attr_accessor server_bundle_output_path: String?
attr_accessor enforce_private_server_bundles: bool

def initialize: (
?node_modules_location: String?,
?server_bundle_js_file: String?,
?prerender: bool?,
?replay_console: bool?,
?make_generated_server_bundle_the_entrypoint: bool?,
?trace: bool?,
?development_mode: bool?,
?defer_generated_component_packs: bool?,
?logging_on_server: bool?,
?server_renderer_pool_size: Integer?,
?server_renderer_timeout: Integer?,
?raise_on_prerender_error: bool,
?skip_display_none: bool?,
?generated_assets_dirs: Array[String]?,
?generated_assets_dir: String?,
?webpack_generated_files: Array[String]?,
?rendering_extension: String?,
?build_test_command: String?,
?build_production_command: String?,
?generated_component_packs_loading_strategy: Symbol?,
?same_bundle_for_client_and_server: bool?,
?i18n_dir: String?,
?i18n_yml_dir: String?,
?i18n_output_format: Symbol?,
?i18n_yml_safe_load_options: Hash[Symbol, untyped]?,
?random_dom_id: bool?,
?server_render_method: String?,
?rendering_props_extension: String?,
?components_subdirectory: String?,
?auto_load_bundle: bool?,
?immediate_hydration: bool?,
?component_registry_timeout: Integer?,
?server_bundle_output_path: String?,
?enforce_private_server_bundles: bool?
) -> void
Comment on lines 25 to 73
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add the missing force_load configuration accessor

ReactOnRails::Configuration exposes a force_load accessor (used to gate hydration in the helper), and recent releases default it to true. Because the accessor and initializer keyword are missing here, typed code can’t call configuration.force_load or set it via configure. Please add the accessor plus the keyword arg:

-    attr_accessor auto_load_bundle: bool
+    attr_accessor auto_load_bundle: bool
+    attr_accessor force_load: bool
@@
-      ?auto_load_bundle: bool?,
+      ?auto_load_bundle: bool?,
+      ?force_load: bool?,

(Place the new keyword next to the related bundle toggles.) This keeps the signature in sync with the Ruby configuration API.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
attr_accessor defer_generated_component_packs: bool
attr_accessor server_render_method: String?
attr_accessor random_dom_id: bool
attr_accessor auto_load_bundle: bool
attr_accessor same_bundle_for_client_and_server: bool
attr_accessor rendering_props_extension: String?
attr_accessor make_generated_server_bundle_the_entrypoint: bool
attr_accessor generated_component_packs_loading_strategy: Symbol?
attr_accessor immediate_hydration: bool
attr_accessor component_registry_timeout: Integer
attr_accessor server_bundle_output_path: String?
attr_accessor enforce_private_server_bundles: bool
def initialize: (
?node_modules_location: String?,
?server_bundle_js_file: String?,
?prerender: bool?,
?replay_console: bool?,
?make_generated_server_bundle_the_entrypoint: bool?,
?trace: bool?,
?development_mode: bool?,
?defer_generated_component_packs: bool?,
?logging_on_server: bool?,
?server_renderer_pool_size: Integer?,
?server_renderer_timeout: Integer?,
?raise_on_prerender_error: bool,
?skip_display_none: bool?,
?generated_assets_dirs: Array[String]?,
?generated_assets_dir: String?,
?webpack_generated_files: Array[String]?,
?rendering_extension: String?,
?build_test_command: String?,
?build_production_command: String?,
?generated_component_packs_loading_strategy: Symbol?,
?same_bundle_for_client_and_server: bool?,
?i18n_dir: String?,
?i18n_yml_dir: String?,
?i18n_output_format: Symbol?,
?i18n_yml_safe_load_options: Hash[Symbol, untyped]?,
?random_dom_id: bool?,
?server_render_method: String?,
?rendering_props_extension: String?,
?components_subdirectory: String?,
?auto_load_bundle: bool?,
?immediate_hydration: bool?,
?component_registry_timeout: Integer?,
?server_bundle_output_path: String?,
?enforce_private_server_bundles: bool?
) -> void
attr_accessor defer_generated_component_packs: bool
attr_accessor server_render_method: String?
attr_accessor random_dom_id: bool
attr_accessor auto_load_bundle: bool
attr_accessor force_load: bool
attr_accessor same_bundle_for_client_and_server: bool
attr_accessor rendering_props_extension: String?
attr_accessor make_generated_server_bundle_the_entrypoint: bool
attr_accessor generated_component_packs_loading_strategy: Symbol?
attr_accessor immediate_hydration: bool
attr_accessor component_registry_timeout: Integer
attr_accessor server_bundle_output_path: String?
attr_accessor enforce_private_server_bundles: bool
def initialize: (
?node_modules_location: String?,
?server_bundle_js_file: String?,
?prerender: bool?,
?replay_console: bool?,
?make_generated_server_bundle_the_entrypoint: bool?,
?trace: bool?,
?development_mode: bool?,
?defer_generated_component_packs: bool?,
?logging_on_server: bool?,
?server_renderer_pool_size: Integer?,
?server_renderer_timeout: Integer?,
?raise_on_prerender_error: bool,
?skip_display_none: bool?,
?generated_assets_dirs: Array[String]?,
?generated_assets_dir: String?,
?webpack_generated_files: Array[String]?,
?rendering_extension: String?,
?build_test_command: String?,
?build_production_command: String?,
?generated_component_packs_loading_strategy: Symbol?,
?same_bundle_for_client_and_server: bool?,
?i18n_dir: String?,
?i18n_yml_dir: String?,
?i18n_output_format: Symbol?,
?i18n_yml_safe_load_options: Hash[Symbol, untyped]?,
?random_dom_id: bool?,
?server_render_method: String?,
?rendering_props_extension: String?,
?components_subdirectory: String?,
?auto_load_bundle: bool?,
?force_load: bool?,
?immediate_hydration: bool?,
?component_registry_timeout: Integer?,
?server_bundle_output_path: String?,
?enforce_private_server_bundles: bool?
) -> void
🤖 Prompt for AI Agents
In sig/react_on_rails/configuration.rbs around lines 25 to 73, the `force_load`
configuration accessor and initializer keyword are missing; add an
`attr_accessor force_load: bool` and add the `?force_load: bool?` keyword
argument to the initialize signature placed next to the related bundle toggles
(e.g., alongside `auto_load_bundle` / `same_bundle_for_client_and_server`) so
the RBS matches the Ruby API and callers can read/set configuration.force_load.


def setup_config_values: () -> void

private

def check_component_registry_timeout: () -> void
def validate_generated_component_packs_loading_strategy: () -> void
def validate_enforce_private_server_bundles: () -> void
def check_minimum_shakapacker_version: () -> void
def check_autobundling_requirements: () -> void
def adjust_precompile_task: () -> void
def error_if_using_packer_and_generated_assets_dir_not_match_public_output_path: () -> void
def check_server_render_method_is_only_execjs: () -> void
def configure_generated_assets_dirs_deprecation: () -> void
def ensure_webpack_generated_files_exists: () -> void
def configure_skip_display_none_deprecation: () -> void
def raise_missing_components_subdirectory: () -> void
def compile_command_conflict_message: () -> String
end
end
11 changes: 11 additions & 0 deletions sig/react_on_rails/controller.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module ReactOnRails
module Controller
def redux_store: (
String store_name,
?props: untyped,
?immediate_hydration: bool?
) -> void

def redux_store_hydration_data: () -> String
end
end
8 changes: 8 additions & 0 deletions sig/react_on_rails/git_utils.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
module ReactOnRails
module GitUtils
def self.uncommitted_changes?: (String path) -> bool
def self.git_installed?: () -> bool
def self.current_branch: () -> String?
def self.rspec_fixture_branches: () -> Array[String]
end
end
57 changes: 57 additions & 0 deletions sig/react_on_rails/helper.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
module ReactOnRails
module Helper
COMPONENT_HTML_KEY: String

# Main helper methods
def react_component: (
String component_name,
?Hash[Symbol, untyped] options
) -> String

def react_component_hash: (
String component_name,
?Hash[Symbol, untyped] options
) -> Hash[String, String]

def redux_store: (
String store_name,
?Hash[Symbol, untyped] props
) -> String

def redux_store_hydration_data: () -> String

def server_render_js: (
String js_expression,
?Hash[Symbol, untyped] options
) -> String

def sanitized_props_string: (untyped props) -> String

def rails_context: (
?server_side: bool
) -> Hash[Symbol, untyped]

private

def internal_react_component: (
String component_name,
Hash[Symbol, untyped] options
) -> Hash[Symbol, untyped]

def build_react_component_result_for_server_rendered_string: (
server_rendered_html: String,
component_specification_tag: String,
console_script: String,
render_options: Hash[Symbol, untyped]
) -> String

def build_react_component_result_for_server_rendered_hash: (
server_rendered_html: Hash[String, untyped],
component_specification_tag: String,
console_script: String,
render_options: Hash[Symbol, untyped]
) -> Hash[String, String]

def prepend_render_rails_context: (String result) -> String
end
end
15 changes: 15 additions & 0 deletions sig/react_on_rails/packer_utils.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module ReactOnRails
module PackerUtils
def self.supports_autobundling?: () -> bool
def self.supports_basic_pack_generation?: () -> bool
def self.supports_async_loading?: () -> bool
def self.nested_entries?: () -> bool
def self.packer_public_output_path: () -> String
def self.precompile?: () -> bool
def self.shakapacker_precompile_hook_configured?: () -> bool
def self.shakapacker_precompile_hook_value: () -> String
def self.raise_shakapacker_version_incompatible_for_autobundling: () -> void
def self.raise_shakapacker_version_incompatible_for_basic_pack_generation: () -> void
def self.raise_nested_entries_disabled: () -> void
end
end
12 changes: 12 additions & 0 deletions sig/react_on_rails/server_rendering_pool.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module ReactOnRails
module ServerRenderingPool
def self.pool: () -> untyped

def self.reset_pool_if_server_bundle_was_modified: () -> void
def self.reset_pool: () -> void
def self.server_render_js_with_console_logging: (
String js_code,
Hash[Symbol, untyped] render_options
) -> Hash[String, untyped]
end
end
11 changes: 11 additions & 0 deletions sig/react_on_rails/test_helper.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
module ReactOnRails
module TestHelper
def self.configure_rspec_to_compile_assets: (untyped config) -> void
def self.ensure_assets_compiled: (?force_compile: bool) -> void
def self.webpack_assets_compiled?: () -> bool

module EnsureAssetsCompiled
def self.has_been_run?: () -> bool
end
end
end
22 changes: 22 additions & 0 deletions sig/react_on_rails/utils.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module ReactOnRails
module Utils
TRUNCATION_FILLER: String

def self.truthy_presence: (untyped obj) -> untyped
def self.wrap_message: (String msg, ?Symbol color) -> String
def self.object_to_boolean: (untyped value) -> bool
def self.server_rendering_is_enabled?: () -> bool
def self.invoke_and_exit_if_failed: (String cmd, String failure_message) -> Array[String]
def self.server_bundle_path_is_http?: () -> bool
def self.bundle_js_file_path: (String bundle_name) -> String
def self.react_on_rails_pro?: () -> bool
def self.server_bundle?: (String bundle_name) -> bool
def self.running_on_windows?: () -> bool
def self.rails_version_less_than?: (String version) -> bool
def self.rails_version_less_than_4_1_1?: () -> bool

module Required
def required: (String name) -> untyped
end
end
end
12 changes: 12 additions & 0 deletions sig/react_on_rails/version_checker.rbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module ReactOnRails
module VersionChecker
def self.log_if_gem_and_node_package_versions_differ: () -> void

private

def self.node_package_version: () -> String?
def self.gem_version: () -> String
def self.node_package_version_different_from_gem?: () -> bool
def self.pr_1683_warning: () -> String
end
end
Loading