react_on_rails 16.2.0.beta.3 → 16.2.0.beta.8

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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +42 -5
  3. data/CLAUDE.md +59 -0
  4. data/CONTRIBUTING.md +49 -1
  5. data/Gemfile.development_dependencies +1 -1
  6. data/Gemfile.lock +25 -10
  7. data/SWITCHING_CI_CONFIGS.md +55 -6
  8. data/Steepfile +51 -0
  9. data/bin/ci-rerun-failures +68 -22
  10. data/bin/ci-run-failed-specs +26 -2
  11. data/bin/ci-switch-config +262 -34
  12. data/bin/lefthook/check-trailing-newlines +2 -12
  13. data/bin/lefthook/eslint-lint +0 -10
  14. data/bin/lefthook/prettier-format +0 -10
  15. data/bin/lefthook/ruby-autofix +3 -6
  16. data/knip.ts +35 -9
  17. data/lib/generators/react_on_rails/templates/base/base/config/initializers/react_on_rails.rb.tt +32 -52
  18. data/lib/generators/react_on_rails/templates/base/base/config/shakapacker.yml +5 -1
  19. data/lib/react_on_rails/configuration.rb +56 -12
  20. data/lib/react_on_rails/controller.rb +3 -3
  21. data/lib/react_on_rails/dev/server_manager.rb +11 -4
  22. data/lib/react_on_rails/doctor.rb +249 -2
  23. data/lib/react_on_rails/helper.rb +12 -3
  24. data/lib/react_on_rails/pro_helper.rb +2 -44
  25. data/lib/react_on_rails/react_component/render_options.rb +7 -7
  26. data/lib/react_on_rails/utils.rb +40 -0
  27. data/lib/react_on_rails/version.rb +1 -1
  28. data/react_on_rails_pro/CHANGELOG.md +142 -29
  29. data/react_on_rails_pro/CONTRIBUTING.md +2 -13
  30. data/react_on_rails_pro/Gemfile.development_dependencies +1 -0
  31. data/react_on_rails_pro/Gemfile.lock +24 -3
  32. data/react_on_rails_pro/README.md +559 -38
  33. data/react_on_rails_pro/docs/code-splitting-loadable-components.md +1 -1
  34. data/react_on_rails_pro/docs/contributors-info/releasing.md +2 -2
  35. data/react_on_rails_pro/docs/installation.md +129 -109
  36. data/react_on_rails_pro/docs/node-renderer/basics.md +29 -22
  37. data/react_on_rails_pro/docs/node-renderer/error-reporting-and-tracing.md +8 -8
  38. data/react_on_rails_pro/docs/node-renderer/js-configuration.md +25 -23
  39. data/react_on_rails_pro/docs/node-renderer/troubleshooting.md +2 -0
  40. data/react_on_rails_pro/docs/updating.md +209 -15
  41. data/react_on_rails_pro/lib/react_on_rails_pro/concerns/stream.rb +58 -4
  42. data/react_on_rails_pro/lib/react_on_rails_pro/configuration.rb +17 -3
  43. data/react_on_rails_pro/lib/react_on_rails_pro/license_public_key.rb +9 -9
  44. data/react_on_rails_pro/lib/react_on_rails_pro/request.rb +41 -25
  45. data/react_on_rails_pro/lib/react_on_rails_pro/stream_request.rb +27 -7
  46. data/react_on_rails_pro/lib/react_on_rails_pro/utils.rb +3 -3
  47. data/react_on_rails_pro/lib/react_on_rails_pro/version.rb +1 -1
  48. data/react_on_rails_pro/package-scripts.yml +1 -1
  49. data/react_on_rails_pro/package.json +5 -8
  50. data/react_on_rails_pro/packages/node-renderer/src/integrations/api.ts +1 -1
  51. data/react_on_rails_pro/packages/node-renderer/src/master/restartWorkers.ts +39 -17
  52. data/react_on_rails_pro/packages/node-renderer/src/master.ts +15 -4
  53. data/react_on_rails_pro/packages/node-renderer/src/shared/configBuilder.ts +44 -5
  54. data/react_on_rails_pro/packages/node-renderer/src/shared/utils.ts +4 -2
  55. data/react_on_rails_pro/packages/node-renderer/src/worker/handleGracefulShutdown.ts +49 -0
  56. data/react_on_rails_pro/packages/node-renderer/src/worker/vm.ts +3 -3
  57. data/react_on_rails_pro/packages/node-renderer/src/worker.ts +5 -2
  58. data/react_on_rails_pro/packages/node-renderer/tests/helper.ts +8 -8
  59. data/react_on_rails_pro/packages/node-renderer/tests/testingNodeRendererConfigs.js +1 -1
  60. data/react_on_rails_pro/packages/node-renderer/tests/worker.test.ts +19 -19
  61. data/react_on_rails_pro/rakelib/public_key_management.rake +6 -5
  62. data/react_on_rails_pro/rakelib/rbs.rake +47 -0
  63. data/react_on_rails_pro/react_on_rails_pro.gemspec +1 -0
  64. data/react_on_rails_pro/sig/react_on_rails_pro/cache.rbs +13 -0
  65. data/react_on_rails_pro/sig/react_on_rails_pro/configuration.rbs +100 -0
  66. data/react_on_rails_pro/sig/react_on_rails_pro/error.rbs +4 -0
  67. data/react_on_rails_pro/sig/react_on_rails_pro/utils.rbs +7 -0
  68. data/react_on_rails_pro/sig/react_on_rails_pro.rbs +5 -0
  69. data/react_on_rails_pro/spec/dummy/Gemfile.lock +23 -3
  70. data/react_on_rails_pro/spec/dummy/app/controllers/pages_controller.rb +3 -3
  71. data/react_on_rails_pro/spec/dummy/bin/dev +4 -8
  72. data/react_on_rails_pro/spec/dummy/client/node-renderer.js +4 -4
  73. data/react_on_rails_pro/spec/dummy/config/environments/production.rb +1 -1
  74. data/react_on_rails_pro/spec/dummy/config/initializers/react_on_rails.rb +28 -12
  75. data/react_on_rails_pro/spec/dummy/config.ru +1 -1
  76. data/react_on_rails_pro/spec/dummy/package.json +2 -2
  77. data/react_on_rails_pro/spec/dummy/spec/helpers/react_on_rails_pro_helper_spec.rb +40 -11
  78. data/react_on_rails_pro/spec/dummy/spec/rails_helper.rb +1 -1
  79. data/react_on_rails_pro/spec/dummy/spec/requests/renderer_console_logging_spec.rb +5 -5
  80. data/react_on_rails_pro/spec/dummy/spec/system/integration_spec.rb +15 -10
  81. data/react_on_rails_pro/spec/dummy/spec/system/renderer_integration_spec.rb +3 -3
  82. data/react_on_rails_pro/spec/dummy/yarn.lock +4 -4
  83. data/react_on_rails_pro/spec/execjs-compatible-dummy/config/environments/production.rb +1 -1
  84. data/react_on_rails_pro/spec/execjs-compatible-dummy/config/initializers/react_on_rails.rb +16 -43
  85. data/react_on_rails_pro/spec/react_on_rails_pro/assets_precompile_spec.rb +15 -18
  86. data/react_on_rails_pro/spec/react_on_rails_pro/cache_spec.rb +1 -1
  87. data/react_on_rails_pro/spec/react_on_rails_pro/configuration_spec.rb +5 -3
  88. data/react_on_rails_pro/spec/react_on_rails_pro/license_validator_spec.rb +27 -12
  89. data/react_on_rails_pro/spec/react_on_rails_pro/request_spec.rb +0 -27
  90. data/react_on_rails_pro/spec/react_on_rails_pro/spec_helper.rb +1 -1
  91. data/react_on_rails_pro/spec/react_on_rails_pro/stream_decorator_spec.rb +89 -0
  92. data/react_on_rails_pro/spec/react_on_rails_pro/stream_spec.rb +144 -0
  93. data/react_on_rails_pro/spec/react_on_rails_pro/support/caching.rb +1 -1
  94. data/react_on_rails_pro/spec/react_on_rails_pro/support/mock_block_helper.rb +4 -2
  95. data/sig/react_on_rails/controller.rbs +1 -1
  96. data/sig/react_on_rails/error.rbs +4 -0
  97. data/sig/react_on_rails/helper.rbs +2 -2
  98. data/sig/react_on_rails/json_parse_error.rbs +10 -0
  99. data/sig/react_on_rails/prerender_error.rbs +21 -0
  100. data/sig/react_on_rails/smart_error.rbs +28 -0
  101. data/sig/react_on_rails.rbs +3 -24
  102. metadata +14 -4
  103. data/lib/react_on_rails/pro_utils.rb +0 -37
  104. data/react_on_rails_pro/spec/dummy/client/app/ror-auto-load-components/TestingStreamableComponent.jsx +0 -15
@@ -105,6 +105,15 @@ else
105
105
  if [[ "$line" =~ rspec[[:space:]]+(\./spec/[^[:space:]]+) ]]; then
106
106
  spec="${BASH_REMATCH[1]}"
107
107
  SPECS+=("$spec")
108
+ # Also handle bare spec paths like "spec/foo.rb[1:2:3]" or "./spec/foo.rb[1:2:3]"
109
+ # Strip trailing % and whitespace
110
+ elif [[ "$line" =~ (\.?/?spec/[^[:space:]%]+) ]]; then
111
+ spec="${BASH_REMATCH[1]}"
112
+ # Normalize to ./spec/ format
113
+ if [[ ! "$spec" =~ ^\. ]]; then
114
+ spec="./$spec"
115
+ fi
116
+ SPECS+=("$spec")
108
117
  fi
109
118
  done
110
119
  fi
@@ -130,7 +139,7 @@ echo ""
130
139
 
131
140
  # Determine the working directory (check if we need to be in spec/dummy)
132
141
  WORKING_DIR="."
133
- if [[ "${UNIQUE_SPECS[0]}" == *"spec/system"* ]] || [[ "${UNIQUE_SPECS[0]}" == *"spec/helpers"* ]]; then
142
+ if [ ${#UNIQUE_SPECS[@]} -gt 0 ] && ([[ "${UNIQUE_SPECS[0]}" == *"spec/system"* ]] || [[ "${UNIQUE_SPECS[0]}" == *"spec/helpers"* ]]); then
134
143
  if [ -d "spec/dummy" ]; then
135
144
  WORKING_DIR="spec/dummy"
136
145
  echo -e "${BLUE}Running from spec/dummy directory${NC}"
@@ -153,9 +162,24 @@ echo ""
153
162
 
154
163
  # Confirm (read from /dev/tty to handle piped input)
155
164
  if [ -t 0 ]; then
165
+ # stdin is a TTY, read directly
156
166
  read -p "Run these specs now? [Y/n] " -n 1 -r REPLY
157
167
  else
158
- read -p "Run these specs now? [Y/n] " -n 1 -r REPLY < /dev/tty
168
+ # stdin is not a TTY (piped input), try /dev/tty
169
+ # Check if we can actually open /dev/tty by attempting to use it in a subshell
170
+ set +e # Temporarily disable errexit for the check
171
+ (exec 0</dev/tty) 2>/dev/null
172
+ TTY_CHECK=$?
173
+ set -e # Re-enable errexit
174
+
175
+ if [ $TTY_CHECK -eq 0 ]; then
176
+ # Successfully opened /dev/tty, use it for confirmation
177
+ read -p "Run these specs now? [Y/n] " -n 1 -r REPLY < /dev/tty
178
+ else
179
+ # Cannot open /dev/tty, auto-confirm
180
+ echo "Run these specs now? [Y/n] Y (auto-confirmed, TTY unavailable)"
181
+ REPLY="Y"
182
+ fi
159
183
  fi
160
184
  echo
161
185
  if [[ ! "${REPLY}" =~ ^[Yy]$ ]] && [[ ! -z "${REPLY}" ]]; then
data/bin/ci-switch-config CHANGED
@@ -39,14 +39,120 @@ check_version_manager() {
39
39
  echo "mise"
40
40
  elif command -v asdf &> /dev/null; then
41
41
  echo "asdf"
42
+ elif command -v rvm &> /dev/null && command -v nvm &> /dev/null; then
43
+ echo "rvm+nvm"
44
+ elif command -v rvm &> /dev/null; then
45
+ echo "rvm"
46
+ elif command -v nvm &> /dev/null; then
47
+ echo "nvm"
42
48
  else
43
- print_error "No version manager found. Please install mise or asdf:"
49
+ print_error "No version manager found. Please install one of:"
44
50
  echo " mise (recommended): https://mise.jdx.dev/"
45
- echo " asdf (legacy): https://asdf-vm.com/"
51
+ echo " asdf: https://asdf-vm.com/"
52
+ echo " rvm + nvm: https://rvm.io/ + https://github.com/nvm-sh/nvm"
46
53
  exit 1
47
54
  fi
48
55
  }
49
56
 
57
+ set_ruby_version() {
58
+ local version="$1"
59
+ local version_manager="$2"
60
+
61
+ case "$version_manager" in
62
+ mise|asdf)
63
+ # Handled via .tool-versions
64
+ ;;
65
+ rvm|rvm+nvm)
66
+ print_header "Setting Ruby $version with rvm"
67
+ # Check if version exists using rvm list rubies for consistent output
68
+ # Anchor to start of line to avoid false matches (e.g., 3.2.8 shouldn't match 13.2.8)
69
+ # Allow optional leading whitespace and ruby- prefix, no end anchor to allow patch suffixes
70
+ if ! rvm list rubies | grep -qE "^[[:space:]]*(ruby-)?${version}"; then
71
+ print_warning "Ruby $version not installed. Installing..."
72
+ if ! rvm install "$version"; then
73
+ print_error "Failed to install Ruby $version with rvm"
74
+ print_warning "Make sure rvm is properly configured. Try running: source ~/.rvm/scripts/rvm"
75
+ exit 1
76
+ fi
77
+ fi
78
+ if ! rvm use "$version"; then
79
+ print_error "Failed to switch to Ruby $version"
80
+ print_warning "Make sure rvm is properly configured. Try running: source ~/.rvm/scripts/rvm"
81
+ exit 1
82
+ fi
83
+ print_success "Switched to Ruby $version"
84
+ ;;
85
+ nvm)
86
+ print_error "Cannot set Ruby version: nvm doesn't manage Ruby"
87
+ echo "Please install one of the following to manage Ruby versions:"
88
+ echo " - rvm: https://rvm.io/"
89
+ echo " - mise: https://mise.jdx.dev/ (recommended, manages both Ruby and Node)"
90
+ echo " - asdf: https://asdf-vm.com/ (manages both Ruby and Node)"
91
+ exit 1
92
+ ;;
93
+ esac
94
+ }
95
+
96
+ set_node_version() {
97
+ local version="$1"
98
+ local version_manager="$2"
99
+
100
+ case "$version_manager" in
101
+ mise|asdf)
102
+ # Handled via .tool-versions
103
+ ;;
104
+ nvm|rvm+nvm)
105
+ print_header "Setting Node $version with nvm"
106
+
107
+ # Source nvm if not already loaded - try multiple common locations
108
+ if ! command -v nvm &> /dev/null; then
109
+ # Try standard nvm location
110
+ if [ -s "$HOME/.nvm/nvm.sh" ]; then
111
+ export NVM_DIR="$HOME/.nvm"
112
+ \. "$NVM_DIR/nvm.sh"
113
+ # Try Homebrew location (macOS)
114
+ elif [ -s "/opt/homebrew/opt/nvm/nvm.sh" ]; then
115
+ export NVM_DIR="/opt/homebrew/opt/nvm"
116
+ \. "/opt/homebrew/opt/nvm/nvm.sh"
117
+ # Try XDG config location
118
+ elif [ -s "${XDG_CONFIG_HOME:-$HOME/.config}/nvm/nvm.sh" ]; then
119
+ export NVM_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/nvm"
120
+ \. "$NVM_DIR/nvm.sh"
121
+ else
122
+ print_error "Could not find nvm installation"
123
+ print_warning "Tried locations: ~/.nvm, /opt/homebrew/opt/nvm, ~/.config/nvm"
124
+ echo "Please source nvm manually or install it from: https://github.com/nvm-sh/nvm"
125
+ exit 1
126
+ fi
127
+ fi
128
+
129
+ # Check if version is already installed using nvm version for reliability
130
+ if ! nvm version "$version" &> /dev/null; then
131
+ print_warning "Node $version not installed. Installing..."
132
+ if ! nvm install "$version"; then
133
+ print_error "Failed to install Node $version with nvm"
134
+ exit 1
135
+ fi
136
+ fi
137
+
138
+ if ! nvm use "$version"; then
139
+ print_error "Failed to switch to Node $version"
140
+ print_warning "Make sure nvm is properly configured. Try running: nvm use $version"
141
+ exit 1
142
+ fi
143
+ print_success "Switched to Node $version"
144
+ ;;
145
+ rvm)
146
+ print_error "Cannot set Node version: rvm doesn't manage Node"
147
+ echo "Please install one of the following to manage Node versions:"
148
+ echo " - nvm: https://github.com/nvm-sh/nvm"
149
+ echo " - mise: https://mise.jdx.dev/ (recommended, manages both Ruby and Node)"
150
+ echo " - asdf: https://asdf-vm.com/ (manages both Ruby and Node)"
151
+ exit 1
152
+ ;;
153
+ esac
154
+ }
155
+
50
156
  show_status() {
51
157
  print_header "Current Configuration"
52
158
  echo ""
@@ -121,14 +227,37 @@ switch_to_minimum() {
121
227
  fi
122
228
 
123
229
  # Set Ruby and Node versions
124
- print_header "Setting runtime versions in .tool-versions"
125
- cat > "$PROJECT_ROOT/.tool-versions" <<EOF
230
+ case "$VERSION_MANAGER" in
231
+ mise|asdf)
232
+ print_header "Setting runtime versions in .tool-versions"
233
+ cat > "$PROJECT_ROOT/.tool-versions" <<EOF
126
234
  ruby 3.2.8
127
235
  nodejs 20.18.1
128
236
  EOF
129
- print_success "Created .tool-versions with Ruby 3.2.8 and Node 20.18.1"
237
+ print_success "Created .tool-versions with Ruby 3.2.8 and Node 20.18.1"
238
+ ;;
239
+ rvm|rvm+nvm)
240
+ print_header "Creating .ruby-version for rvm"
241
+ echo "3.2.8" > "$PROJECT_ROOT/.ruby-version"
242
+ print_success "Created .ruby-version with Ruby 3.2.8"
243
+ ;;
244
+ esac
245
+
246
+ case "$VERSION_MANAGER" in
247
+ nvm|rvm+nvm)
248
+ print_header "Creating .nvmrc for nvm"
249
+ echo "20.18.1" > "$PROJECT_ROOT/.nvmrc"
250
+ print_success "Created .nvmrc with Node 20.18.1"
251
+ ;;
252
+ esac
253
+
254
+ set_ruby_version "3.2.8" "$VERSION_MANAGER"
255
+ set_node_version "20.18.1" "$VERSION_MANAGER"
130
256
 
131
257
  # Run conversion script
258
+ # NOTE: This uses whatever 'ruby' is in PATH after version manager updates above.
259
+ # The version manager may not have reloaded yet, so ensure your current Ruby is
260
+ # compatible with script/convert (Ruby 2.6+ should work).
132
261
  print_header "Running script/convert to downgrade dependencies"
133
262
  cd "$PROJECT_ROOT"
134
263
  ruby script/convert
@@ -158,22 +287,60 @@ EOF
158
287
 
159
288
  # Reload version manager to pick up new versions
160
289
  print_header "Reloading $VERSION_MANAGER to use new versions"
161
- if [[ "$VERSION_MANAGER" == "mise" ]]; then
162
- # mise will auto-detect .tool-versions on next cd
163
- :
164
- elif [ -f "$HOME/.asdf/asdf.sh" ]; then
165
- source "$HOME/.asdf/asdf.sh"
166
- fi
290
+ case "$VERSION_MANAGER" in
291
+ mise)
292
+ # mise will auto-detect .tool-versions on next cd
293
+ ;;
294
+ asdf)
295
+ # Note: This only affects the script's subshell, not the user's current shell
296
+ if [ -f "$HOME/.asdf/asdf.sh" ]; then
297
+ source "$HOME/.asdf/asdf.sh"
298
+ fi
299
+ ;;
300
+ rvm|rvm+nvm)
301
+ # Versions already set via rvm use
302
+ ;;
303
+ nvm)
304
+ # Version already set via nvm use
305
+ ;;
306
+ esac
167
307
 
168
308
  echo ""
169
309
  print_success "Switched to MINIMUM configuration"
170
- print_warning "Run these commands to reload your shell and verify:"
310
+
311
+ case "$VERSION_MANAGER" in
312
+ rvm+nvm|rvm|nvm)
313
+ print_warning "IMPORTANT: Version changes in this script don't persist to your current shell."
314
+ print_warning "The rvm/nvm commands run in a subshell and cannot affect your terminal."
315
+ echo ""
316
+ print_warning "Choose one of these options to activate the new versions:"
317
+ echo " Option 1 (Recommended): Open a new terminal and cd into the project"
318
+ echo " Option 2: Source your shell config:"
319
+ [ "$VERSION_MANAGER" = "rvm" ] || [ "$VERSION_MANAGER" = "rvm+nvm" ] && echo " source ~/.rvm/scripts/rvm"
320
+ [ "$VERSION_MANAGER" = "nvm" ] || [ "$VERSION_MANAGER" = "rvm+nvm" ] && echo " source \$NVM_DIR/nvm.sh"
321
+ echo ""
322
+ ;;
323
+ esac
324
+
325
+ print_warning "After activating versions, verify with:"
171
326
  echo " cd $PROJECT_ROOT"
172
- if [[ "$VERSION_MANAGER" == "mise" ]]; then
173
- echo " mise current"
174
- else
175
- echo " asdf current"
176
- fi
327
+ case "$VERSION_MANAGER" in
328
+ mise)
329
+ echo " mise current"
330
+ ;;
331
+ asdf)
332
+ echo " asdf current"
333
+ ;;
334
+ rvm+nvm)
335
+ echo " rvm current && nvm current"
336
+ ;;
337
+ rvm)
338
+ echo " rvm current"
339
+ ;;
340
+ nvm)
341
+ echo " nvm current"
342
+ ;;
343
+ esac
177
344
  echo ""
178
345
  print_warning "Next steps to build and test:"
179
346
  echo " rake node_package"
@@ -201,18 +368,41 @@ restore_to_latest() {
201
368
  fi
202
369
 
203
370
  # Set Ruby and Node versions
204
- print_header "Setting runtime versions in .tool-versions"
205
- cat > "$PROJECT_ROOT/.tool-versions" <<EOF
371
+ case "$VERSION_MANAGER" in
372
+ mise|asdf)
373
+ print_header "Setting runtime versions in .tool-versions"
374
+ cat > "$PROJECT_ROOT/.tool-versions" <<EOF
206
375
  ruby 3.4.3
207
376
  nodejs 22.12.0
208
377
  EOF
209
- print_success "Created .tool-versions with Ruby 3.4.3 and Node 22.12.0"
378
+ print_success "Created .tool-versions with Ruby 3.4.3 and Node 22.12.0"
379
+ ;;
380
+ rvm|rvm+nvm)
381
+ print_header "Creating .ruby-version for rvm"
382
+ echo "3.4.3" > "$PROJECT_ROOT/.ruby-version"
383
+ print_success "Created .ruby-version with Ruby 3.4.3"
384
+ ;;
385
+ esac
386
+
387
+ case "$VERSION_MANAGER" in
388
+ nvm|rvm+nvm)
389
+ print_header "Creating .nvmrc for nvm"
390
+ echo "22.12.0" > "$PROJECT_ROOT/.nvmrc"
391
+ print_success "Created .nvmrc with Node 22.12.0"
392
+ ;;
393
+ esac
394
+
395
+ set_ruby_version "3.4.3" "$VERSION_MANAGER"
396
+ set_node_version "22.12.0" "$VERSION_MANAGER"
210
397
 
211
398
  # Restore files from git
212
399
  print_header "Restoring dependency files from git"
213
400
  cd "$PROJECT_ROOT"
214
- git restore Gemfile.development_dependencies package.json spec/dummy/package.json packages/react-on-rails-pro/package.json 2>/dev/null || true
215
- print_success "Files restored from git"
401
+ if ! git restore Gemfile.development_dependencies package.json spec/dummy/package.json packages/react-on-rails-pro/package.json 2>/dev/null; then
402
+ print_warning "Some files could not be restored (may not exist in git)"
403
+ else
404
+ print_success "Files restored from git"
405
+ fi
216
406
 
217
407
  # Clean and reinstall
218
408
  print_header "Cleaning node_modules and reinstalling"
@@ -238,22 +428,60 @@ EOF
238
428
 
239
429
  # Reload version manager to pick up new versions
240
430
  print_header "Reloading $VERSION_MANAGER to use new versions"
241
- if [[ "$VERSION_MANAGER" == "mise" ]]; then
242
- # mise will auto-detect .tool-versions on next cd
243
- :
244
- elif [ -f "$HOME/.asdf/asdf.sh" ]; then
245
- source "$HOME/.asdf/asdf.sh"
246
- fi
431
+ case "$VERSION_MANAGER" in
432
+ mise)
433
+ # mise will auto-detect .tool-versions on next cd
434
+ ;;
435
+ asdf)
436
+ # Note: This only affects the script's subshell, not the user's current shell
437
+ if [ -f "$HOME/.asdf/asdf.sh" ]; then
438
+ source "$HOME/.asdf/asdf.sh"
439
+ fi
440
+ ;;
441
+ rvm|rvm+nvm)
442
+ # Versions already set via rvm use
443
+ ;;
444
+ nvm)
445
+ # Version already set via nvm use
446
+ ;;
447
+ esac
247
448
 
248
449
  echo ""
249
450
  print_success "Restored to LATEST configuration"
250
- print_warning "Run these commands to reload your shell and verify:"
451
+
452
+ case "$VERSION_MANAGER" in
453
+ rvm+nvm|rvm|nvm)
454
+ print_warning "IMPORTANT: Version changes in this script don't persist to your current shell."
455
+ print_warning "The rvm/nvm commands run in a subshell and cannot affect your terminal."
456
+ echo ""
457
+ print_warning "Choose one of these options to activate the new versions:"
458
+ echo " Option 1 (Recommended): Open a new terminal and cd into the project"
459
+ echo " Option 2: Source your shell config:"
460
+ [ "$VERSION_MANAGER" = "rvm" ] || [ "$VERSION_MANAGER" = "rvm+nvm" ] && echo " source ~/.rvm/scripts/rvm"
461
+ [ "$VERSION_MANAGER" = "nvm" ] || [ "$VERSION_MANAGER" = "rvm+nvm" ] && echo " source \$NVM_DIR/nvm.sh"
462
+ echo ""
463
+ ;;
464
+ esac
465
+
466
+ print_warning "After activating versions, verify with:"
251
467
  echo " cd $PROJECT_ROOT"
252
- if [[ "$VERSION_MANAGER" == "mise" ]]; then
253
- echo " mise current"
254
- else
255
- echo " asdf current"
256
- fi
468
+ case "$VERSION_MANAGER" in
469
+ mise)
470
+ echo " mise current"
471
+ ;;
472
+ asdf)
473
+ echo " asdf current"
474
+ ;;
475
+ rvm+nvm)
476
+ echo " rvm current && nvm current"
477
+ ;;
478
+ rvm)
479
+ echo " rvm current"
480
+ ;;
481
+ nvm)
482
+ echo " nvm current"
483
+ ;;
484
+ esac
257
485
  echo ""
258
486
  print_warning "Next steps to build and test:"
259
487
  echo " rake node_package"
@@ -16,23 +16,13 @@ else
16
16
  echo "🔍 Checking trailing newlines on $CONTEXT files..."
17
17
  fi
18
18
 
19
- failed_files=""
20
19
  for file in $files; do
21
20
  if [ -f "$file" ] && [ -s "$file" ]; then
22
21
  if ! tail -c 1 "$file" | grep -q '^$'; then
23
- echo " Missing trailing newline: $file"
24
- failed_files="$failed_files $file"
22
+ echo "🔧 Adding trailing newline to: $file"
23
+ echo >> "$file"
25
24
  fi
26
25
  fi
27
26
  done
28
27
 
29
- if [ -n "$failed_files" ]; then
30
- echo ""
31
- echo "❌ Trailing newline check failed!"
32
- echo "💡 Add trailing newlines to:$failed_files"
33
- echo "🔧 Quick fix: for file in$failed_files; do echo >> \"\$file\"; done"
34
- echo "🚫 Skip hook: git commit --no-verify"
35
- exit 1
36
- fi
37
-
38
28
  echo "✅ All files have proper trailing newlines"
@@ -34,11 +34,6 @@ if [ -n "$root_and_packages_pro_files" ]; then
34
34
  if ! yarn run eslint $root_and_packages_pro_files --fix; then
35
35
  exit_code=1
36
36
  fi
37
-
38
- # Re-stage files if running on staged or all-changed context
39
- if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
40
- echo $root_and_packages_pro_files | xargs -r git add
41
- fi
42
37
  fi
43
38
 
44
39
  # Lint react_on_rails_pro files (using Pro gem's ESLint config)
@@ -56,11 +51,6 @@ if [ -n "$react_on_rails_pro_files" ]; then
56
51
  if ! (cd react_on_rails_pro && yarn run eslint $react_on_rails_pro_files_relative --fix); then
57
52
  exit_code=1
58
53
  fi
59
-
60
- # Re-stage files if running on staged or all-changed context
61
- if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
62
- echo $react_on_rails_pro_files | xargs -r git add
63
- fi
64
54
  fi
65
55
 
66
56
  if [ $exit_code -eq 0 ]; then
@@ -24,11 +24,6 @@ if [ -n "$root_files" ]; then
24
24
  printf " %s\n" $root_files
25
25
 
26
26
  yarn run prettier --write $root_files
27
-
28
- # Re-stage files if running on staged or all-changed context
29
- if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
30
- echo $root_files | xargs -r git add
31
- fi
32
27
  fi
33
28
 
34
29
  # Format Pro files (using Pro's Prettier config)
@@ -44,11 +39,6 @@ if [ -n "$pro_files" ]; then
44
39
  pro_files_relative=$(echo "$pro_files" | sed 's|^react_on_rails_pro/||')
45
40
 
46
41
  (cd react_on_rails_pro && yarn run prettier --write $pro_files_relative)
47
-
48
- # Re-stage files if running on staged or all-changed context
49
- if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
50
- echo $pro_files | xargs -r git add
51
- fi
52
42
  fi
53
43
 
54
44
  echo "✅ Prettier formatting complete"
@@ -17,10 +17,7 @@ else
17
17
  fi
18
18
  printf " %s\n" $files
19
19
 
20
- bundle exec rake autofix
20
+ # Run RuboCop only on changed files (not the full rake autofix)
21
+ bundle exec rubocop -A --force-exclusion -- $files
21
22
 
22
- # Re-stage files if running on staged or all-changed context
23
- if [ "$CONTEXT" = "staged" ] || [ "$CONTEXT" = "all-changed" ]; then
24
- echo $files | xargs -r git add
25
- echo "✅ Re-staged formatted files"
26
- fi
23
+ echo "✅ Auto-fix complete (fixed files staged automatically)"
data/knip.ts CHANGED
@@ -5,13 +5,11 @@ const config: KnipConfig = {
5
5
  workspaces: {
6
6
  // Root workspace - manages the monorepo and global tooling
7
7
  '.': {
8
- entry: ['eslint.config.ts'],
8
+ entry: ['eslint.config.ts', 'jest.config.base.js'],
9
9
  project: ['*.{js,mjs,ts}'],
10
10
  ignoreBinaries: [
11
11
  // Has to be installed globally
12
12
  'yalc',
13
- // Used in package.json scripts (devDependency, so unlisted in production mode)
14
- 'nps',
15
13
  // Pro package binaries used in Pro workflows
16
14
  'playwright',
17
15
  'e2e-test',
@@ -41,6 +39,17 @@ const config: KnipConfig = {
41
39
  // SWC transpiler dependencies used in dummy apps
42
40
  '@swc/core',
43
41
  'swc-loader',
42
+ // Test dependencies used by child workspaces (packages/react-on-rails, packages/react-on-rails-pro)
43
+ '@testing-library/dom',
44
+ '@testing-library/jest-dom',
45
+ '@testing-library/react',
46
+ '@types/react-dom',
47
+ 'create-react-class',
48
+ 'jest-fetch-mock',
49
+ 'prop-types',
50
+ 'react',
51
+ 'react-dom',
52
+ 'redux',
44
53
  ],
45
54
  },
46
55
 
@@ -89,6 +98,11 @@ const config: KnipConfig = {
89
98
  'src/RSCRoute.tsx:RSCRouteProps',
90
99
  'src/streamServerRenderedReactComponent.ts:StreamingTrackers',
91
100
  ],
101
+ ignoreDependencies: [
102
+ // Test dependencies used only in tests
103
+ '@types/mock-fs',
104
+ 'mock-fs',
105
+ ],
92
106
  },
93
107
  'spec/dummy': {
94
108
  entry: [
@@ -112,6 +126,12 @@ const config: KnipConfig = {
112
126
  '**/app-react16/**/*',
113
127
  // Playwright support files and helpers - generated by cypress-on-rails gem
114
128
  'e2e/playwright/support/**',
129
+ // Components and files used dynamically by React on Rails (registered at runtime)
130
+ 'client/app/actions/**',
131
+ 'client/app/components/**',
132
+ 'client/app/routes/**',
133
+ 'client/app/startup/**',
134
+ 'client/app/store/**',
115
135
  ],
116
136
  project: ['**/*.{js,cjs,mjs,jsx,ts,cts,mts,tsx}!', 'config/webpack/*.js'],
117
137
  paths: {
@@ -124,9 +144,6 @@ const config: KnipConfig = {
124
144
  'bin/.*',
125
145
  ],
126
146
  ignoreDependencies: [
127
- // Build-time dependencies not detected by Knip in any mode
128
- '@babel/runtime',
129
- 'mini-css-extract-plugin',
130
147
  // There's no ReScript plugin for Knip
131
148
  '@rescript/react',
132
149
  // The Babel plugin fails to detect it
@@ -136,18 +153,27 @@ const config: KnipConfig = {
136
153
  'node-libs-browser',
137
154
  // The below dependencies are not detected by the Webpack plugin
138
155
  // due to the config issue.
139
- 'css-loader',
140
156
  'expose-loader',
141
157
  'file-loader',
142
158
  'imports-loader',
143
159
  'null-loader',
144
- 'sass',
145
- 'sass-loader',
146
160
  'sass-resources-loader',
147
161
  'style-loader',
148
162
  'url-loader',
149
163
  // Transitive dependency of shakapacker but listed as direct dependency
150
164
  'webpack-merge',
165
+ // Dependencies not detected in production mode
166
+ '@babel/runtime',
167
+ 'mini-css-extract-plugin',
168
+ 'css-loader',
169
+ 'sass',
170
+ 'sass-loader',
171
+ // Dependencies used dynamically by React on Rails
172
+ 'create-react-class',
173
+ 'react-helmet',
174
+ '@types/react-helmet',
175
+ 'react-redux',
176
+ 'react-router-dom',
151
177
  ],
152
178
  },
153
179
  },