react_on_rails 16.1.2 → 16.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (106) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +2 -0
  3. data/.rubocop.yml +85 -0
  4. data/Gemfile.development_dependencies +8 -7
  5. data/Gemfile.lock +158 -119
  6. data/Steepfile +56 -0
  7. data/lib/generators/react_on_rails/base_generator.rb +43 -120
  8. data/lib/generators/react_on_rails/dev_tests_generator.rb +2 -1
  9. data/lib/generators/react_on_rails/generator_helper.rb +102 -2
  10. data/lib/generators/react_on_rails/install_generator.rb +36 -156
  11. data/lib/generators/react_on_rails/js_dependency_manager.rb +383 -0
  12. data/lib/generators/react_on_rails/templates/base/base/.dev-services.yml.example +76 -0
  13. data/lib/generators/react_on_rails/templates/base/base/bin/shakapacker-precompile-hook +30 -0
  14. data/lib/generators/react_on_rails/templates/base/base/bin/switch-bundler +141 -0
  15. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +44 -45
  16. data/lib/generators/react_on_rails/templates/base/base/config/{shakapacker.yml → shakapacker.yml.tt} +28 -3
  17. data/lib/generators/react_on_rails/templates/base/base/config/webpack/development.js.tt +15 -9
  18. data/lib/generators/react_on_rails/templates/base/base/config/webpack/serverWebpackConfig.js.tt +42 -6
  19. data/lib/react_on_rails/configuration.rb +149 -32
  20. data/lib/react_on_rails/controller.rb +3 -3
  21. data/lib/react_on_rails/dev/pack_generator.rb +168 -2
  22. data/lib/react_on_rails/dev/process_manager.rb +136 -14
  23. data/lib/react_on_rails/dev/server_manager.rb +194 -26
  24. data/lib/react_on_rails/dev/service_checker.rb +200 -0
  25. data/lib/react_on_rails/doctor.rb +341 -12
  26. data/lib/react_on_rails/engine.rb +75 -1
  27. data/lib/react_on_rails/git_utils.rb +3 -1
  28. data/lib/react_on_rails/helper.rb +70 -192
  29. data/lib/react_on_rails/locales/base.rb +17 -5
  30. data/lib/react_on_rails/packer_utils.rb +79 -2
  31. data/lib/react_on_rails/packs_generator.rb +57 -39
  32. data/lib/react_on_rails/prerender_error.rb +74 -17
  33. data/lib/react_on_rails/pro_helper.rb +64 -0
  34. data/lib/react_on_rails/react_component/render_options.rb +7 -7
  35. data/lib/react_on_rails/server_rendering_pool/ruby_embedded_java_script.rb +2 -5
  36. data/lib/react_on_rails/smart_error.rb +326 -0
  37. data/lib/react_on_rails/system_checker.rb +8 -9
  38. data/lib/react_on_rails/test_helper/webpack_assets_status_checker.rb +16 -7
  39. data/lib/react_on_rails/utils.rb +241 -55
  40. data/lib/react_on_rails/version.rb +1 -1
  41. data/lib/react_on_rails/version_checker.rb +383 -35
  42. data/lib/tasks/generate_packs.rake +12 -6
  43. data/lib/tasks/locale.rake +6 -1
  44. data/rakelib/docker.rake +26 -0
  45. data/rakelib/dummy_apps.rake +30 -0
  46. data/rakelib/example_type.rb +121 -0
  47. data/rakelib/examples_config.yml +52 -0
  48. data/rakelib/lint.rake +52 -0
  49. data/rakelib/node_package.rake +15 -0
  50. data/rakelib/rbs.rake +70 -0
  51. data/rakelib/run_rspec.rake +223 -0
  52. data/rakelib/shakapacker_examples.rake +171 -0
  53. data/rakelib/task_helpers.rb +134 -0
  54. data/rakelib/update_changelog.rake +73 -0
  55. data/react_on_rails.gemspec +4 -3
  56. data/sig/README.md +52 -0
  57. data/sig/react_on_rails/configuration.rbs +96 -0
  58. data/sig/react_on_rails/controller.rbs +15 -0
  59. data/sig/react_on_rails/dev/file_manager.rbs +15 -0
  60. data/sig/react_on_rails/dev/pack_generator.rbs +19 -0
  61. data/sig/react_on_rails/dev/process_manager.rbs +22 -0
  62. data/sig/react_on_rails/dev/server_manager.rbs +39 -0
  63. data/sig/react_on_rails/dev/service_checker.rbs +22 -0
  64. data/sig/react_on_rails/error.rbs +4 -0
  65. data/sig/react_on_rails/generators/js_dependency_manager.rbs +123 -0
  66. data/sig/react_on_rails/git_utils.rbs +8 -0
  67. data/sig/react_on_rails/helper.rbs +65 -0
  68. data/sig/react_on_rails/json_parse_error.rbs +10 -0
  69. data/sig/react_on_rails/locales.rbs +46 -0
  70. data/sig/react_on_rails/packer_utils.rbs +15 -0
  71. data/sig/react_on_rails/prerender_error.rbs +21 -0
  72. data/sig/react_on_rails/server_rendering_pool.rbs +12 -0
  73. data/sig/react_on_rails/smart_error.rbs +28 -0
  74. data/sig/react_on_rails/test_helper.rbs +11 -0
  75. data/sig/react_on_rails/utils.rbs +34 -0
  76. data/sig/react_on_rails/version_checker.rbs +12 -0
  77. data/sig/react_on_rails.rbs +17 -0
  78. metadata +49 -32
  79. data/AI_AGENT_INSTRUCTIONS.md +0 -63
  80. data/CHANGELOG.md +0 -1836
  81. data/CLAUDE.md +0 -135
  82. data/CODING_AGENTS.md +0 -313
  83. data/CONTRIBUTING.md +0 -668
  84. data/Dockerfile_tests +0 -12
  85. data/KUDOS.md +0 -114
  86. data/LICENSE.md +0 -47
  87. data/LICENSES/README.md +0 -14
  88. data/NEWS.md +0 -62
  89. data/PROJECTS.md +0 -63
  90. data/REACT-ON-RAILS-PRO-LICENSE.md +0 -129
  91. data/README.md +0 -217
  92. data/SUMMARY.md +0 -88
  93. data/TODO.md +0 -135
  94. data/bin/lefthook/check-trailing-newlines +0 -38
  95. data/bin/lefthook/get-changed-files +0 -26
  96. data/bin/lefthook/prettier-format +0 -26
  97. data/bin/lefthook/ruby-autofix +0 -26
  98. data/bin/lefthook/ruby-lint +0 -27
  99. data/docker-compose.yml +0 -11
  100. data/eslint.config.ts +0 -232
  101. data/knip.ts +0 -114
  102. data/lib/react_on_rails/pro/NOTICE +0 -21
  103. data/lib/react_on_rails/pro/helper.rb +0 -122
  104. data/lib/react_on_rails/pro/utils.rb +0 -53
  105. data/tsconfig.eslint.json +0 -6
  106. data/tsconfig.json +0 -19
@@ -0,0 +1,171 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Defines tasks related to generating example apps using the gem's generator.
4
+ # Allows us to create and test apps generated using a wide range of options.
5
+ #
6
+ # Also see example_type.rb
7
+
8
+ require "yaml"
9
+ require "rails/version"
10
+ require "pathname"
11
+ require "json"
12
+
13
+ require_relative "example_type"
14
+ require_relative "task_helpers"
15
+
16
+ namespace :shakapacker_examples do # rubocop:disable Metrics/BlockLength
17
+ include ReactOnRails::TaskHelpers
18
+
19
+ # Updates React-related dependencies to a specific version
20
+ def update_react_dependencies(deps, react_version)
21
+ return unless deps
22
+
23
+ deps["react"] = react_version
24
+ deps["react-dom"] = react_version
25
+ end
26
+
27
+ # Updates Shakapacker to minimum supported version in either dependencies or devDependencies
28
+ def update_shakapacker_dependency(deps, dev_deps)
29
+ if dev_deps&.key?("shakapacker")
30
+ dev_deps["shakapacker"] = ExampleType::MINIMUM_SHAKAPACKER_VERSION
31
+ elsif deps&.key?("shakapacker")
32
+ deps["shakapacker"] = ExampleType::MINIMUM_SHAKAPACKER_VERSION
33
+ end
34
+ end
35
+
36
+ # Updates dependencies in package.json to use specific React version
37
+ def update_package_json_for_react_version(package_json_path, react_version)
38
+ return unless File.exist?(package_json_path)
39
+
40
+ begin
41
+ package_json = JSON.parse(File.read(package_json_path))
42
+ rescue JSON::ParserError => e
43
+ puts " ERROR: Failed to parse #{package_json_path}: #{e.message}"
44
+ raise
45
+ end
46
+
47
+ deps = package_json["dependencies"]
48
+ dev_deps = package_json["devDependencies"]
49
+
50
+ update_react_dependencies(deps, react_version)
51
+ # Shakapacker 8.2.0 requires webpack-assets-manifest ^5.x (v6.x uses ESM and breaks)
52
+ # Always add this explicitly since the transitive dependency from shakapacker may be v6.x
53
+ dev_deps["webpack-assets-manifest"] = "^5.0.6" if dev_deps
54
+ # Shakapacker 8.2.0 requires babel-loader to be explicitly installed as a devDependency
55
+ # (in 9.x this requirement was relaxed or the package structure changed)
56
+ dev_deps["babel-loader"] = "^9.1.3" if dev_deps
57
+ # @babel/plugin-transform-runtime is required by the default babel config but not
58
+ # automatically included as a dependency in older Shakapacker versions
59
+ dev_deps["@babel/plugin-transform-runtime"] = "^7.24.0" if dev_deps
60
+ update_shakapacker_dependency(deps, dev_deps)
61
+
62
+ # Add npm overrides to force specific React version, preventing yalc-linked
63
+ # react-on-rails from pulling in React 19 as a transitive dependency
64
+ package_json["overrides"] = {
65
+ "react" => react_version,
66
+ "react-dom" => react_version
67
+ }
68
+
69
+ File.write(package_json_path, "#{JSON.pretty_generate(package_json)}\n")
70
+ end
71
+
72
+ # Updates Gemfile to pin shakapacker to minimum version
73
+ # (must match the npm package version exactly)
74
+ def update_gemfile_versions(gemfile_path)
75
+ return unless File.exist?(gemfile_path)
76
+
77
+ gemfile_content = File.read(gemfile_path)
78
+ # Replace any shakapacker gem line with exact version pin
79
+ # Handle both single-line: gem 'shakapacker', '>= 8.2.0'
80
+ # And multi-line declarations:
81
+ # gem 'shakapacker',
82
+ # '>= 8.2.0'
83
+ gemfile_content = gemfile_content.gsub(
84
+ /gem ['"]shakapacker['"][^\n]*(?:\n\s+[^g\n][^\n]*)*$/m,
85
+ "gem 'shakapacker', '#{ExampleType::MINIMUM_SHAKAPACKER_VERSION}'"
86
+ )
87
+ File.write(gemfile_path, gemfile_content)
88
+ end
89
+
90
+ # Updates package.json and Gemfile to use specific React version for compatibility testing
91
+ def apply_react_version(dir, react_version)
92
+ update_package_json_for_react_version(File.join(dir, "package.json"), react_version)
93
+ update_gemfile_versions(File.join(dir, "Gemfile"))
94
+
95
+ puts " Updated package.json for compatibility testing:"
96
+ puts " React: #{react_version}"
97
+ puts " Shakapacker: #{ExampleType::MINIMUM_SHAKAPACKER_VERSION}"
98
+ end
99
+
100
+ # Define tasks for each example type
101
+ ExampleType.all[:shakapacker_examples].each do |example_type| # rubocop:disable Metrics/BlockLength
102
+ relative_gem_root = Pathname(gem_root).relative_path_from(Pathname(example_type.dir))
103
+ # CLOBBER
104
+ desc "Clobbers (deletes) #{example_type.name_pretty}"
105
+ task example_type.clobber_task_name_short do
106
+ rm_rf(example_type.dir)
107
+ end
108
+
109
+ # GENERATE
110
+ desc "Generates #{example_type.name_pretty}"
111
+ task example_type.gen_task_name_short => example_type.clobber_task_name do
112
+ puts "Running shakapacker_examples:#{example_type.gen_task_name_short}"
113
+ mkdir_p(example_type.dir)
114
+ sh_in_dir(examples_dir, "rails new #{example_type.name} #{example_type.rails_options} --skip-javascript")
115
+ sh_in_dir(example_type.dir, "touch .gitignore")
116
+ sh_in_dir(example_type.dir,
117
+ "echo \"gem 'react_on_rails', path: '#{relative_gem_root}'\" >> #{example_type.gemfile}")
118
+ # Pin to 9.4.0 to ensure gem and npm package versions match
119
+ # (shakapacker 9.5.0 gem was released but npm package version detection has issues)
120
+ sh_in_dir(example_type.dir, "echo \"gem 'shakapacker', '9.4.0'\" >> #{example_type.gemfile}")
121
+ bundle_install_in(example_type.dir)
122
+ sh_in_dir(example_type.dir, "rake shakapacker:install")
123
+ # Skip validation when running generators on example apps during development.
124
+ # The generator validates that certain config options exist in the initializer,
125
+ # but during example generation, we're often testing against the current gem
126
+ # codebase which may have new config options not yet in the released version.
127
+ # This allows examples to be generated without validation errors while still
128
+ # testing the generator functionality.
129
+ generator_commands = example_type.generator_shell_commands.map do |cmd|
130
+ "REACT_ON_RAILS_SKIP_VALIDATION=true #{cmd}"
131
+ end
132
+ sh_in_dir(example_type.dir, generator_commands)
133
+ # Re-run bundle install since dev_tests generator adds rspec-rails and coveralls to Gemfile
134
+ bundle_install_in(example_type.dir)
135
+
136
+ # Apply specific React version for compatibility testing examples
137
+ if example_type.pinned_react_version?
138
+ apply_react_version(example_type.dir, example_type.react_version_string)
139
+ # Re-run bundle install since Gemfile was updated with pinned shakapacker version
140
+ bundle_install_in(example_type.dir)
141
+ # Run npm install BEFORE shakapacker:binstubs to ensure the npm shakapacker version
142
+ # matches the gem version. The binstubs task loads the Rails environment which
143
+ # validates version matching between gem and npm package.
144
+ # Use --legacy-peer-deps to avoid peer dependency conflicts when yalc-linked
145
+ # react-on-rails expects newer React versions
146
+ sh_in_dir(example_type.dir, "npm install --legacy-peer-deps")
147
+ # Regenerate Shakapacker binstubs after downgrading from 9.x to 8.2.x
148
+ # The binstub format may differ between major versions
149
+ unbundled_sh_in_dir(example_type.dir, "bundle exec rake shakapacker:binstubs")
150
+ else
151
+ sh_in_dir(example_type.dir, "npm install")
152
+ end
153
+ # Generate the component packs after running the generator to ensure all
154
+ # auto-bundled components have corresponding pack files created.
155
+ # Use unbundled_sh_in_dir to ensure we're using the generated app's Gemfile
156
+ # and gem versions, not the parent workspace's bundle context.
157
+ unbundled_sh_in_dir(example_type.dir, "bundle exec rake react_on_rails:generate_packs")
158
+ end
159
+ end
160
+
161
+ desc "Clobbers (deletes) all example apps"
162
+ task :clobber do
163
+ rm_rf(examples_dir)
164
+ end
165
+
166
+ desc "Generates all example apps"
167
+ task gen_all: ExampleType.all[:shakapacker_examples].map(&:gen_task_name)
168
+ end
169
+
170
+ desc "Generates all example apps. Run `rake -D examples` to see all available options"
171
+ task shakapacker_examples: ["shakapacker_examples:gen_all"]
@@ -0,0 +1,134 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "English"
4
+
5
+ module ReactOnRails
6
+ module TaskHelpers
7
+ # Returns the root folder of the monorepo
8
+ def monorepo_root
9
+ File.expand_path("../..", __dir__)
10
+ end
11
+
12
+ # Returns the root folder of the react_on_rails gem
13
+ def gem_root
14
+ File.join(monorepo_root, "react_on_rails")
15
+ end
16
+
17
+ # Returns the folder where examples are located
18
+ def examples_dir
19
+ File.join(monorepo_root, "gen-examples", "examples")
20
+ end
21
+
22
+ def dummy_app_dir
23
+ File.join(gem_root, "spec/dummy")
24
+ end
25
+
26
+ # Executes a string or an array of strings in a shell in the given directory in an unbundled environment
27
+ def sh_in_dir(dir, *shell_commands)
28
+ shell_commands.flatten.each { |shell_command| sh %(cd #{dir} && #{shell_command.strip}) }
29
+ end
30
+
31
+ # Executes a string or an array of strings in a shell in the given directory
32
+ def unbundled_sh_in_dir(dir, *shell_commands)
33
+ Dir.chdir(dir) do
34
+ # Without `with_unbundled_env`, running bundle in the child directories won't correctly
35
+ # update the Gemfile.lock
36
+ Bundler.with_unbundled_env do
37
+ shell_commands.flatten.each do |shell_command|
38
+ sh(shell_command.strip)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ def bundle_install_in(dir)
45
+ required_version = detect_bundler_ruby_version(dir)
46
+
47
+ if required_version && required_version != RUBY_VERSION
48
+ puts " Switching Ruby version: #{RUBY_VERSION} → #{required_version}"
49
+ # Run version switch and bundle install in the same shell context
50
+ bundle_install_with_ruby_version(dir, required_version)
51
+ else
52
+ unbundled_sh_in_dir(dir, "bundle install")
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ # Runs bundle install with the specified Ruby version in the same shell context
59
+ def bundle_install_with_ruby_version(dir, version)
60
+ version_manager = ENV.fetch("RUBY_VERSION_MANAGER", "rvm")
61
+
62
+ command = case version_manager
63
+ when "rvm"
64
+ "rvm #{version} do bundle install"
65
+ when "rbenv"
66
+ "RBENV_VERSION=#{version} bundle install"
67
+ when "asdf"
68
+ "asdf shell ruby #{version} && bundle install"
69
+ else
70
+ # TODO: add support for chruby
71
+ puts " ⚠️ Unknown RUBY_VERSION_MANAGER: #{version_manager}"
72
+ puts " Supported values: rvm, rbenv, asdf"
73
+ raise "Ruby version #{version} required. Current: #{RUBY_VERSION}"
74
+ end
75
+
76
+ unbundled_sh_in_dir(dir, command)
77
+ rescue StandardError => e
78
+ puts " ⚠️ Failed to switch Ruby version and run bundle install: #{e.message}"
79
+ puts " Please manually switch to Ruby #{version} and try again"
80
+ raise
81
+ end
82
+
83
+ # Detects the required Ruby version using Bundler
84
+ def detect_bundler_ruby_version(dir)
85
+ output = nil
86
+ exit_status = nil
87
+
88
+ # Run in unbundled environment to avoid conflicts with parent Bundler context
89
+ Bundler.with_unbundled_env do
90
+ Dir.chdir(dir) do
91
+ output = `bundle platform --ruby 2>&1`
92
+ exit_status = $CHILD_STATUS.exitstatus
93
+ end
94
+ end
95
+
96
+ unless exit_status.zero?
97
+ puts " ⚠️ Failed to detect Ruby version in #{dir}"
98
+ puts " Error: #{output.strip}" unless output.strip.empty?
99
+ return nil
100
+ end
101
+
102
+ # Parse "ruby 3.3.7" or "ruby 3.3.7-rc1" or "ruby 3.4.0-preview1"
103
+ # Regex matches: digits.dots followed by optional -prerelease
104
+ match = output.strip.match(/ruby\s+([\d.]+(?:-[a-zA-Z0-9.]+)?)/)
105
+ match ? match[1] : nil
106
+ rescue StandardError => e
107
+ puts " ⚠️ Error detecting Ruby version: #{e.message}"
108
+ nil
109
+ end
110
+
111
+ public
112
+
113
+ def bundle_install_in_no_turbolinks(dir)
114
+ sh_in_dir(dir, "DISABLE_TURBOLINKS=TRUE bundle install")
115
+ end
116
+
117
+ # Runs bundle exec using that directory's Gemfile
118
+ def bundle_exec(dir: nil, args: nil, env_vars: "")
119
+ sh_in_dir(dir, "#{env_vars} bundle exec #{args}")
120
+ end
121
+
122
+ def generators_source_dir
123
+ File.join(gem_root, "lib/generators/react_on_rails")
124
+ end
125
+
126
+ def symbolize_keys(hash)
127
+ hash.each_with_object({}) do |(key, value), new_hash|
128
+ new_key = key.is_a?(String) ? key.to_sym : key
129
+ new_value = value.is_a?(Hash) ? symbolize_keys(value) : value
130
+ new_hash[new_key] = new_value
131
+ end
132
+ end
133
+ end
134
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "English"
4
+ require "bundler"
5
+ require_relative "task_helpers"
6
+
7
+ CLAUDE_CODE_TIP = <<~TIP
8
+ ┌─────────────────────────────────────────────────────────────────────────────┐
9
+ │ TIP: This task only adds version headers and links, not changelog entries. │
10
+ │ For full automation, run /update-changelog in Claude Code. │
11
+ │ │
12
+ │ After running this task, manually add entries under the new header: │
13
+ │ #### Fixed / #### Added / #### Changed / etc. │
14
+ └─────────────────────────────────────────────────────────────────────────────┘
15
+ TIP
16
+
17
+ # Update the compare links at the bottom of the changelog
18
+ # version: version string without 'v' prefix (e.g., "16.2.0.beta.20")
19
+ # anchor: markdown anchor (e.g., "[16.2.0.beta.20]")
20
+ def update_changelog_links(changelog, version, anchor)
21
+ compare_link_prefix = "https://github.com/shakacode/react_on_rails/compare"
22
+ match_data = %r{#{compare_link_prefix}/(?<prev_version>.*)\.\.\.master}.match(changelog)
23
+ return unless match_data
24
+
25
+ prev_version = match_data[:prev_version]
26
+ new_unreleased_link = "#{compare_link_prefix}/#{version}...master"
27
+ new_version_link = "#{anchor}: #{compare_link_prefix}/#{prev_version}...#{version}"
28
+ changelog.sub!(match_data[0], "#{new_unreleased_link}\n#{new_version_link}")
29
+ end
30
+
31
+ # Insert version header into changelog, returns true if successful
32
+ def insert_version_header(changelog, anchor, tag_date)
33
+ # Try inserting right after ### [Unreleased] first
34
+ return true if changelog.sub!("### [Unreleased]", "### [Unreleased]\n\n### #{anchor} - #{tag_date}")
35
+
36
+ # Fallback: insert after "Changes since the last non-beta release."
37
+ return true if changelog.sub!("Changes since the last non-beta release.", "\\0\n\n### #{anchor} - #{tag_date}")
38
+
39
+ false
40
+ end
41
+
42
+ desc "Updates CHANGELOG.md inserting headers for the new version (headers only, not content).
43
+ Argument: Git tag. Defaults to the latest tag.
44
+ TIP: Use /update-changelog in Claude Code for full automation."
45
+
46
+ task :update_changelog, %i[tag] do |_, args|
47
+ puts CLAUDE_CODE_TIP
48
+
49
+ # Git tags use 'v' prefix (e.g., v16.2.0), but CHANGELOG uses versions without it
50
+ git_tag = args[:tag] || `git describe --tags --abbrev=0`.strip
51
+ changelog_version = git_tag.delete_prefix("v")
52
+ anchor = "[#{changelog_version}]"
53
+ changelog = File.read("CHANGELOG.md")
54
+
55
+ if changelog.include?(anchor)
56
+ puts "Tag #{git_tag} is already documented in CHANGELOG.md"
57
+ next
58
+ end
59
+
60
+ tag_date = `git show -s --format=%cs #{git_tag} 2>&1`.split("\n").last&.strip
61
+ abort("Failed to find tag #{git_tag}") unless $CHILD_STATUS.success? && tag_date
62
+
63
+ unless insert_version_header(changelog, anchor, tag_date)
64
+ abort("Failed to insert version header: could not find '### [Unreleased]' " \
65
+ "or 'Changes since the last non-beta release.' in CHANGELOG.md")
66
+ end
67
+
68
+ update_changelog_links(changelog, changelog_version, anchor)
69
+
70
+ File.write("CHANGELOG.md", changelog)
71
+ puts "Updated CHANGELOG.md with version header for #{git_tag}"
72
+ puts "NOTE: You still need to write the changelog entries manually."
73
+ end
@@ -16,9 +16,10 @@ Gem::Specification.new do |s|
16
16
  s.homepage = "https://github.com/shakacode/react_on_rails"
17
17
  s.license = "MIT"
18
18
 
19
- s.files = `git ls-files -z`.split("\x0").reject do |f|
20
- f.match(%r{^(docs|test|spec|features|gen-examples|tmp|node_modules|node_package|coverage|rakelib|script)/}) ||
21
- f.match(%r{^(jest\.config\.js|book\.json|package\.json|package-scripts\.yml|yarn\.lock|\..*)})
19
+ s.files = Dir.chdir(__dir__) do
20
+ `git ls-files -z`.split("\x0").reject do |f|
21
+ f.match(%r{^(spec|tmp)/})
22
+ end
22
23
  end
23
24
  s.bindir = "exe"
24
25
  s.executables = s.files.grep(%r{^exe/}) { |f| File.basename(f) }
data/sig/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # RBS Type Signatures
2
+
3
+ This directory contains RBS (Ruby Signature) type definitions for the React on Rails gem.
4
+
5
+ ## What is RBS?
6
+
7
+ RBS is Ruby's official type signature language. It provides type information for Ruby code, enabling:
8
+
9
+ - Better IDE support and autocomplete
10
+ - Static type checking with tools like Steep
11
+ - Improved documentation
12
+ - Early detection of type-related bugs
13
+
14
+ ## Structure
15
+
16
+ The signatures are organized to mirror the `lib/` directory structure:
17
+
18
+ - `react_on_rails.rbs` - Main module and core classes
19
+ - `react_on_rails/configuration.rbs` - Configuration class types
20
+ - `react_on_rails/helper.rbs` - View helper method signatures
21
+ - `react_on_rails/server_rendering_pool.rbs` - Server rendering types
22
+ - `react_on_rails/utils.rbs` - Utility method signatures
23
+ - And more...
24
+
25
+ ## Validation
26
+
27
+ To validate the RBS signatures:
28
+
29
+ ```bash
30
+ bundle exec rake rbs:validate
31
+ ```
32
+
33
+ Or directly:
34
+
35
+ ```bash
36
+ bundle exec rbs -I sig validate
37
+ ```
38
+
39
+ To list all RBS files:
40
+
41
+ ```bash
42
+ bundle exec rake rbs:list
43
+ ```
44
+
45
+ ## Development
46
+
47
+ When adding new public methods or classes to the gem, please also add corresponding RBS signatures.
48
+
49
+ For more information about RBS:
50
+
51
+ - [RBS Documentation](https://github.com/ruby/rbs)
52
+ - [RBS Syntax Guide](https://github.com/ruby/rbs/blob/master/docs/syntax.md)
@@ -0,0 +1,96 @@
1
+ module ReactOnRails
2
+ class Configuration
3
+ attr_accessor node_modules_location: String?
4
+ attr_accessor server_bundle_js_file: String
5
+ attr_accessor prerender: bool
6
+ attr_accessor replay_console: bool
7
+ attr_accessor trace: bool
8
+ attr_accessor development_mode: bool
9
+ attr_accessor logging_on_server: bool
10
+ attr_accessor server_renderer_pool_size: Integer
11
+ attr_accessor server_renderer_timeout: Integer
12
+ attr_accessor skip_display_none: bool?
13
+ attr_accessor raise_on_prerender_error: bool
14
+ attr_accessor generated_assets_dirs: Array[String]?
15
+ attr_accessor generated_assets_dir: String
16
+ attr_accessor components_subdirectory: String?
17
+ attr_accessor webpack_generated_files: Array[String]
18
+ attr_accessor rendering_extension: String?
19
+ attr_accessor build_test_command: String
20
+ attr_accessor build_production_command: String
21
+ attr_accessor i18n_dir: String?
22
+ attr_accessor i18n_yml_dir: String?
23
+ attr_accessor i18n_output_format: Symbol?
24
+ attr_accessor i18n_yml_safe_load_options: Hash[Symbol, untyped]?
25
+ attr_accessor defer_generated_component_packs: bool
26
+ attr_accessor server_render_method: String?
27
+ attr_accessor random_dom_id: bool
28
+ attr_accessor auto_load_bundle: bool
29
+ attr_accessor same_bundle_for_client_and_server: bool
30
+ attr_accessor rendering_props_extension: String?
31
+ attr_accessor make_generated_server_bundle_the_entrypoint: bool
32
+ attr_accessor generated_component_packs_loading_strategy: Symbol?
33
+ attr_accessor immediate_hydration: bool
34
+ attr_accessor component_registry_timeout: Integer
35
+ attr_accessor server_bundle_output_path: String?
36
+ attr_accessor enforce_private_server_bundles: bool
37
+
38
+ def initialize: (
39
+ ?node_modules_location: String?,
40
+ ?server_bundle_js_file: String?,
41
+ ?prerender: bool?,
42
+ ?replay_console: bool?,
43
+ ?make_generated_server_bundle_the_entrypoint: bool?,
44
+ ?trace: bool?,
45
+ ?development_mode: bool?,
46
+ ?defer_generated_component_packs: bool?,
47
+ ?logging_on_server: bool?,
48
+ ?server_renderer_pool_size: Integer?,
49
+ ?server_renderer_timeout: Integer?,
50
+ ?raise_on_prerender_error: bool?,
51
+ ?skip_display_none: bool?,
52
+ ?generated_assets_dirs: Array[String]?,
53
+ ?generated_assets_dir: String?,
54
+ ?webpack_generated_files: Array[String]?,
55
+ ?rendering_extension: String?,
56
+ ?build_test_command: String?,
57
+ ?build_production_command: String?,
58
+ ?generated_component_packs_loading_strategy: Symbol?,
59
+ ?same_bundle_for_client_and_server: bool?,
60
+ ?i18n_dir: String?,
61
+ ?i18n_yml_dir: String?,
62
+ ?i18n_output_format: Symbol?,
63
+ ?i18n_yml_safe_load_options: Hash[Symbol, untyped]?,
64
+ ?random_dom_id: bool?,
65
+ ?server_render_method: String?,
66
+ ?rendering_props_extension: String?,
67
+ ?components_subdirectory: String?,
68
+ ?auto_load_bundle: bool?,
69
+ ?immediate_hydration: bool?,
70
+ ?component_registry_timeout: Integer?,
71
+ ?server_bundle_output_path: String?,
72
+ ?enforce_private_server_bundles: bool?
73
+ ) -> void
74
+
75
+ def setup_config_values: () -> void
76
+
77
+ private
78
+
79
+ def check_component_registry_timeout: () -> void
80
+ def validate_generated_component_packs_loading_strategy: () -> void
81
+ def validate_enforce_private_server_bundles: () -> void
82
+ def check_minimum_shakapacker_version: () -> void
83
+ def check_autobundling_requirements: () -> void
84
+ def adjust_precompile_task: () -> void
85
+ def error_if_using_packer_and_generated_assets_dir_not_match_public_output_path: () -> void
86
+ def check_server_render_method_is_only_execjs: () -> void
87
+ def configure_generated_assets_dirs_deprecation: () -> void
88
+ def ensure_webpack_generated_files_exists: () -> void
89
+ def configure_skip_display_none_deprecation: () -> void
90
+ def raise_missing_components_subdirectory: () -> void
91
+ def compile_command_conflict_message: () -> String
92
+ def rsc_bundle_js_file: () -> String?
93
+ def react_client_manifest_file: () -> String?
94
+ def react_server_client_manifest_file: () -> String?
95
+ end
96
+ end
@@ -0,0 +1,15 @@
1
+ module ReactOnRails
2
+ module Controller
3
+ # Type alias for ActiveSupport::SafeBuffer (html_safe strings)
4
+ type safe_buffer = String
5
+
6
+ def redux_store: (
7
+ String store_name,
8
+ ?props: Hash[Symbol, untyped] | String,
9
+ ?immediate_hydration: bool
10
+ ) -> void
11
+
12
+ # Returns html_safe string (ActiveSupport::SafeBuffer)
13
+ def redux_store_hydration_data: () -> safe_buffer
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ module ReactOnRails
2
+ module Dev
3
+ class FileManager
4
+ def self.cleanup_stale_files: () -> bool
5
+
6
+ private
7
+
8
+ def self.cleanup_overmind_sockets: () -> bool
9
+ def self.cleanup_rails_pid_file: () -> bool
10
+ def self.overmind_running?: () -> bool
11
+ def self.process_running?: (Integer) -> bool
12
+ def self.remove_file_if_exists: (String, String) -> bool
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ module ReactOnRails
2
+ module Dev
3
+ class PackGenerator
4
+ def self.generate: (?verbose: bool) -> void
5
+
6
+ private
7
+
8
+ def self.run_pack_generation: (?silent: bool, ?verbose: bool) -> bool
9
+ def self.should_run_directly?: () -> bool
10
+ def self.rails_available?: () -> bool
11
+ def self.run_rake_task_directly: (?silent: bool) -> bool
12
+ def self.load_rake_tasks: () -> void
13
+ def self.prepare_rake_task: () -> untyped
14
+ def self.capture_output: (bool) { () -> bool } -> bool
15
+ def self.handle_rake_error: (Exception, bool) -> void
16
+ def self.run_via_bundle_exec: (?silent: bool, ?verbose: bool) -> (bool | nil)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ module ReactOnRails
2
+ module Dev
3
+ class ProcessManager
4
+ VERSION_CHECK_TIMEOUT: Integer
5
+
6
+ def self.installed?: (String) -> bool
7
+ def self.ensure_procfile: (String) -> void
8
+ def self.run_with_process_manager: (String) -> void
9
+
10
+ private
11
+
12
+ def self.installed_in_current_context?: (String) -> bool
13
+ def self.version_flags_for: (String) -> Array[String]
14
+ def self.run_process_if_available: (String, Array[String]) -> (bool | nil)
15
+ def self.run_process_outside_bundle: (String, Array[String]) -> bool
16
+ def self.process_available_in_system?: (String) -> bool
17
+ def self.with_unbundled_context: () { () -> untyped } -> untyped
18
+ def self.show_process_manager_installation_help: () -> void
19
+ def self.valid_procfile_path?: (String) -> bool
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,39 @@
1
+ module ReactOnRails
2
+ module Dev
3
+ class ServerManager
4
+ type mode = :development | :production_like | :static | :hmr
5
+
6
+ def self.start: (mode, String?, ?verbose: bool, ?route: String?, ?rails_env: String?) -> void
7
+ def self.kill_processes: () -> void
8
+ def self.development_processes: () -> Hash[String, String]
9
+ def self.kill_running_processes: () -> bool
10
+ def self.find_process_pids: (String) -> Array[Integer]
11
+ def self.terminate_processes: (Array[Integer]) -> void
12
+ def self.kill_port_processes: (Array[Integer]) -> bool
13
+ def self.find_port_pids: (Integer) -> Array[Integer]
14
+ def self.cleanup_socket_files: () -> bool
15
+ def self.print_kill_summary: (bool) -> void
16
+ def self.show_help: () -> void
17
+ def self.run_from_command_line: (?Array[String]) -> void
18
+
19
+ private
20
+
21
+ def self.help_usage: () -> String
22
+ def self.help_commands: () -> String
23
+ def self.help_options: () -> String
24
+ def self.help_customization: () -> String
25
+ def self.help_mode_details: () -> String
26
+ def self.help_troubleshooting: () -> String
27
+ def self.run_production_like: (?_verbose: bool, ?route: String?, ?rails_env: String?) -> void
28
+ def self.run_static_development: (String, ?verbose: bool, ?route: String?) -> void
29
+ def self.run_development: (String, ?verbose: bool, ?route: String?) -> void
30
+ def self.print_server_info: (String, Array[String], ?Integer, ?route: String?) -> void
31
+ def self.print_procfile_info: (String, ?route: String?) -> void
32
+ def self.procfile_port: (String) -> Integer
33
+ def self.box_border: (Integer) -> String
34
+ def self.box_bottom: (Integer) -> String
35
+ def self.box_empty_line: (Integer) -> String
36
+ def self.format_box_line: (String, Integer) -> String
37
+ end
38
+ end
39
+ end