Skip to content

Commit

Permalink
feat: Improved error message for build errors
Browse files Browse the repository at this point in the history
  • Loading branch information
joelmoss committed Sep 25, 2023
1 parent 968063c commit 4122980
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 13 deletions.
15 changes: 10 additions & 5 deletions lib/proscenium/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,12 +46,17 @@ module Request
end

class BuildError < StandardError
attr_reader :error, :path
attr_reader :error

def initialize(path, error)
error = Oj.load(error, mode: :strict).deep_transform_keys(&:underscore)
def initialize(error)
@error = Oj.load(error, mode: :strict).deep_transform_keys(&:underscore)

super "Failed to build '#{path}' -- #{error['text']}"
msg = @error['text']
if (location = @error['location'])
msg << " at #{location['file']}:#{location['line']}:#{location['column']}"
end

super msg
end
end

Expand Down Expand Up @@ -86,7 +91,7 @@ def build(path) # rubocop:disable Metrics/AbcSize
engines.to_json,
Proscenium.config.debug)

raise BuildError.new(path, result[:response]) unless result[:success]
raise BuildError, result[:response] unless result[:success]

result[:response]
end
Expand Down
6 changes: 3 additions & 3 deletions lib/proscenium/middleware/esbuild.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ def initialize(args)
end

def attempt
render_response Proscenium::Builder.build(path_to_build, root: Rails.root.to_s,
base_url: @request.base_url)
rescue Proscenium::Builder::CompileError => e
render_response Builder.build(path_to_build, root: Rails.root.to_s,
base_url: @request.base_url)
rescue Builder::CompileError => e
raise self.class::CompileError, { file: @request.fullpath, detail: e.message }, caller
end
end
Expand Down
8 changes: 8 additions & 0 deletions lib/proscenium/monkey.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,14 @@
module Proscenium
# rubocop:disable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/PerceivedComplexity
module Monkey
module DebugView
def initialize(assigns)
paths = [RESCUES_TEMPLATE_PATH, Rails.root.join('lib', 'templates').to_s]
lookup_context = ActionView::LookupContext.new(paths)
super(lookup_context, assigns, nil)
end
end

module TemplateRenderer
private

Expand Down
16 changes: 15 additions & 1 deletion lib/proscenium/railtie.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,17 @@ class Railtie < ::Rails::Engine
# end
config.proscenium.engines = Set.new

config.action_dispatch.rescue_templates = {
'Proscenium::Builder::BuildError' => 'build_error'
}

initializer 'proscenium.middleware' do |app|
app.middleware.insert_after ActionDispatch::Static, Middleware
# app.middleware.insert_after ActionDispatch::Static, Rack::ETag, 'no-cache'
# app.middleware.insert_after ActionDispatch::Static, Rack::ConditionalGet
end

initializer 'proscenium.monkey_views' do
initializer 'proscenium.monkey_patches' do
ActiveSupport.on_load(:action_view) do
ActionView::TemplateRenderer.prepend Monkey::TemplateRenderer
ActionView::PartialRenderer.prepend Monkey::PartialRenderer
Expand All @@ -65,3 +69,13 @@ class Railtie < ::Rails::Engine
end
end
end

# Monkey path ActionDispatch::DebugView to use our custom error template on BuildError exceptions.
class ActionDispatch::DebugView
def initialize(assigns)
paths = [RESCUES_TEMPLATE_PATH,
Proscenium::Railtie.root.join('lib', 'proscenium', 'templates').to_s]
lookup_context = ActionView::LookupContext.new(paths)
super(lookup_context, assigns, nil)
end
end
27 changes: 27 additions & 0 deletions lib/proscenium/templates/rescues/build_error.html.erb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<header>
<h1>
<%= @exception.class.to_s %>
</h1>
</header>

<main role="main" id="container">
<%= render "rescues/message_and_suggestions", exception: @exception %>
<% if @exception.error['location'] %>
<div class="source">
<div class="data">
<pre>

<%= @exception.error['location']['file'] %>:<%= @exception.error['location']['line'] %>:<%= @exception.error['location']['column'] %>
<%= @exception.error['location']['line'].to_s.rjust 5 %><%= @exception.error['location']['line_text'] %>
<%= (@exception.error['location']['length'] > 1 ? "~" * @exception.error['location']['length'] : "^").rjust(@exception.error['location']['column'] + @exception.error['location']['length']) %>
<%- if @exception.error['location']['suggestion'].present? -%> + │ <%= @exception.error['location']['suggestion'].rjust(@exception.error['location']['column'] + 1) %>
<% else %> <%- end -%>
</pre>
</div>
</div>
<% end %>
<%= render template: "rescues/_request_and_response" %>
</main>
8 changes: 4 additions & 4 deletions test/proscenium/builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ def before
with '.build' do
it 'builds multiple files' do
expect(subject.build('lib/code_splitting/son.js;lib/code_splitting/daughter.js')).to be == %(
lib/code_splitting/son.js::public/assets/lib/code_splitting/son$LAGMAD6O$.js;
lib/code_splitting/daughter.js::public/assets/lib/code_splitting/daughter$7JJ2HGHC$.js
).gsub(/[[:space:]]/, '')
lib/code_splitting/son.js::public/assets/lib/code_splitting/son$LAGMAD6O$.js;
lib/code_splitting/daughter.js::public/assets/lib/code_splitting/daughter$7JJ2HGHC$.js
).gsub(/[[:space:]]/, '')
end

it 'replaces NODE_ENV and RAILS_ENV' do
Expand All @@ -33,7 +33,7 @@ def before
expect do
subject.build('unknown.js')
end.to raise_exception(Proscenium::Builder::BuildError,
message: be == "Failed to build 'unknown.js' -- Could not resolve \"unknown.js\"")
message: be == 'Could not resolve "unknown.js"')
end
end
end
Expand Down

0 comments on commit 4122980

Please sign in to comment.