Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 96 additions & 2 deletions lib/react_on_rails/dev/pack_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@ class << self
def generate(verbose: false)
if verbose
puts "📦 Generating React on Rails packs..."
success = system "bundle exec rake react_on_rails:generate_packs"
success = run_pack_generation
else
print "📦 Generating packs... "
success = system "bundle exec rake react_on_rails:generate_packs > /dev/null 2>&1"
success = run_pack_generation(silent: true)
puts success ? "✅" : "❌"
end

Expand All @@ -21,6 +21,100 @@ def generate(verbose: false)
puts "❌ Pack generation failed"
exit 1
end

private

def run_pack_generation(silent: false)
# If we're already inside a Bundler context AND Rails is available (e.g., called from bin/dev),
# we can directly require and run the task. Otherwise, use bundle exec.
if should_run_directly?
run_rake_task_directly(silent: silent)
else
run_via_bundle_exec(silent: silent)
end
end

def should_run_directly?
# Check if we're in a meaningful Bundler context with BUNDLE_GEMFILE
return false unless defined?(Bundler)
return false unless ENV["BUNDLE_GEMFILE"]
return false unless rails_available?

true
end

def rails_available?
return false unless defined?(Rails)
return false unless Rails.respond_to?(:application)
return false if Rails.application.nil?

# Verify Rails app can actually load tasks
begin
Rails.application.respond_to?(:load_tasks)
rescue StandardError
false
end
end

def run_rake_task_directly(silent: false)
require "rake"

load_rake_tasks
task = prepare_rake_task

capture_output(silent) do
task.invoke
true
end
rescue StandardError => e
handle_rake_error(e, silent)
false
end

def load_rake_tasks
return if Rake::Task.task_defined?("react_on_rails:generate_packs")

Rails.application.load_tasks
end

def prepare_rake_task
task = Rake::Task["react_on_rails:generate_packs"]
task.reenable # Allow re-execution if called multiple times
task
end

def capture_output(silent)
return yield unless silent

original_stdout = $stdout
original_stderr = $stderr
output_buffer = StringIO.new
$stdout = output_buffer
$stderr = output_buffer

begin
yield
ensure
$stdout = original_stdout
$stderr = original_stderr
end
end

def handle_rake_error(error, _silent)
error_msg = "Error generating packs: #{error.message}"
error_msg += "\n#{error.backtrace.join("\n")}" if ENV["DEBUG"]

# Always write to stderr, even in silent mode
warn error_msg
end

def run_via_bundle_exec(silent: false)
if silent
system "bundle exec rake react_on_rails:generate_packs > /dev/null 2>&1"
else
system "bundle exec rake react_on_rails:generate_packs"
end
end
end
end
end
Expand Down
Loading